Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix wlr/workspaces to support labwc #3967

Open
nabzord opened this issue Mar 4, 2025 · 2 comments · May be fixed by #4016
Open

Fix wlr/workspaces to support labwc #3967

nabzord opened this issue Mar 4, 2025 · 2 comments · May be fixed by #4016

Comments

@nabzord
Copy link

nabzord commented Mar 4, 2025

now that labwc has merged support for wayland protocol ext_workspaces_manager_v1, some fixes probably need to be made to this old codebase to support labwc or other wlr based compositors.

@nabzord
Copy link
Author

nabzord commented Mar 5, 2025

  • I made the below example written in C for detecting "Workspace 1" events but I could not figure out how to send requests to the wayland proxy to change active or current workspace.

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <wayland-client.h>
#include "ext-workspace-v1-client-protocol.h"

struct wl_display *display = NULL;
struct wl_compositor *compositor = NULL;
struct ext_workspace_manager_v1 *workspace_manager = NULL;

static const struct ext_workspace_manager_v1_listener workspace_manager_listener;
static const struct ext_workspace_handle_v1_listener workspace_handle_listener;

struct workspace_data {
char name[256]; // Store the workspace name
};

static void global_registry_handler(void *data, struct wl_registry *registry, uint32_t id,
const char *interface, uint32_t version)
{
printf("Got a registry event for %s id %d\n", interface, id);
if (strcmp(interface, "wl_compositor") == 0)
compositor = wl_registry_bind(registry,
id,
&wl_compositor_interface,
1);
if (strcmp(interface, "ext_workspace_manager_v1") == 0) {
workspace_manager = wl_registry_bind(registry,
id,
&ext_workspace_manager_v1_interface,
1);

    ext_workspace_manager_v1_add_listener(workspace_manager, &workspace_manager_listener, NULL);
}

}

static void global_registry_remover(void *data, struct wl_registry *registry, uint32_t id)
{
printf("Got a registry losing event for %d\n", id);
}

static const struct wl_registry_listener registry_listener = {
global_registry_handler,
global_registry_remover
};

static void workspace_id(void *data, struct ext_workspace_handle_v1 *workspace, const char *id) {
printf("Workspace ID: %s\n", id);
}

static void workspace_name(void *data, struct ext_workspace_handle_v1 *workspace, const char *new_name) {
//printf("Workspace name: %s\n", name);
if (!data || !new_name) {
fprintf(stderr, "workspace_name: NULL data or new_name\n");
return;
}

struct workspace_data *ws_data = (struct workspace_data *)data;
strncpy(ws_data->name, new_name, sizeof(ws_data->name) - 1);
ws_data->name[sizeof(ws_data->name) - 1] = '\0';  // Ensure null termination

printf("Workspace name updated: %s\n", ws_data->name);

}

static void workspace_coordinates(void *data, struct ext_workspace_handle_v1 *workspace, struct wl_array *coordinates) {
printf("Workspace Coordinates: ");
// Assuming you need to print each coordinate (e.g., for an array of integers)
for (size_t i = 0; i < coordinates->size / sizeof(int); i++) {
printf("%d ", ((int *)coordinates->data)[i]);
}
printf("\n");
}

static void workspace_state(void *data, struct ext_workspace_handle_v1 *workspace, uint32_t state) {
// Assuming the workspace name is passed along with the event
//printf("Workspace state changed: %u\n", state);
if (!data) {
fprintf(stderr, "workspace_state: NULL data\n");
return;
}

struct workspace_data *ws_data = (struct workspace_data *)data;
//printf("Workspace '%s' state changed: %u\n", ws_data->name, state);
if (state == 1 && strcmp(ws_data->name, "Workspace 1") == 0) {
    printf("{\"text\": \"1\", \"class\": \"activated\"}\n");
    fflush(stdout); // Ensure immediate output for Waybar
} else if (state == 0 && strcmp(ws_data->name, "Workspace 1") == 0) {
    printf("{\"text\": \"1\", \"class\": \"deactivated\"}\n");
    fflush(stdout); // Ensure immediate output for Waybar
}

}

static void workspace_capabilities(void *data, struct ext_workspace_handle_v1 *workspace, uint32_t capabilities) {
printf("Workspace capabilities: %u\n", capabilities);
}

static void workspace_removed(void *data, struct ext_workspace_handle_v1 *workspace) {
printf("Workspace removed\n");
}

static void workspace_group_event(void *data, struct ext_workspace_manager_v1 *manager, struct ext_workspace_group_handle_v1 *group_handle) {
printf("Workspace group event triggered\n");
// Handle the workspace group event
}

static void workspace_event(void *data, struct ext_workspace_manager_v1 *manager, struct ext_workspace_handle_v1 *workspace) {
printf("Received workspace event for new workspace\n");
// Logic for handling "workspace" events.
//void (listener)(void) = (void ()(void)) &workspace_handle_listener;
//wl_proxy_add_listener((struct wl_proxy *)workspace, listener, NULL);
struct workspace_data *ws_data = calloc(1, sizeof(struct workspace_data));
if (!ws_data) {
fprintf(stderr, "Failed to allocate workspace_data\n");
return;
}
ext_workspace_handle_v1_add_listener(workspace, &workspace_handle_listener, ws_data);

}

static void done_event(void *data, struct ext_workspace_manager_v1 *manager) {
printf("Done event triggered\n\n");
// Logic for handling "done" events.
}

static void finished_event(void *data, struct ext_workspace_manager_v1 *manager) {
printf("Finished event triggered\n");
// Logic for handling "finished" events.
}

static const struct ext_workspace_handle_v1_listener workspace_handle_listener = {
.id = workspace_id,
.name = workspace_name,
.coordinates = workspace_coordinates,
.state = workspace_state,
.capabilities = workspace_capabilities,
.removed = workspace_removed,
};

static const struct ext_workspace_manager_v1_listener workspace_manager_listener = {
.workspace_group = workspace_group_event, // Now correctly matches the expected type
.workspace = workspace_event,
.done = done_event,
.finished = finished_event
};

int main(int argc, char **argv) {

display = wl_display_connect(NULL);
if (display == NULL) {
fprintf(stderr, "Can't connect to display\n");
exit(1);
}
printf("connected to display\n");

struct wl_registry *registry = wl_display_get_registry(display);
wl_registry_add_listener(registry, &registry_listener, NULL);

wl_display_dispatch(display);
wl_display_roundtrip(display);

if (compositor == NULL) {
fprintf(stderr, "Can't find compositor\n");
exit(1);
} else {
fprintf(stderr, "Found compositor\n");
}

if (workspace_manager == NULL) {
    fprintf(stderr, "Can't find workspace_manager\n");
    exit(1);
    } else {
    fprintf(stderr, "Found workspace_manager\n\n");
    }


while (wl_display_dispatch(display) != -1) {
    // Ensure the listener is added once and not in every loop

}
    
    


wl_display_disconnect(display);
printf("disconnected from display\n");

exit(0);

}

@jp7677
Copy link

jp7677 commented Mar 30, 2025

@nabzord See #4016 for a good start into this direction.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging a pull request may close this issue.

2 participants