wayland: Phase 57 — icccm_set/get/free_command store WM_COMMAND in view
Add wm_command/wm_command_n fields to wl_toplevel_view. wl_icccm_set_command stores a deep copy of argv in the view struct; wl_icccm_get_command returns a NULL-terminated heap copy (caller frees each string plus the array via wl_icccm_free_command). handle_toplevel_destroy frees the stored command on cleanup. Update getCommandForWindow in misc.c: when dpy is NULL (Wayland path), call wm_backend->icccm_get_command instead of returning NULL immediately. This allows fixLeaderProperties and session.c to retrieve the command string for Wayland-managed windows. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
parent
e727bdbad0
commit
2c6e24dfb0
|
|
@ -39,6 +39,8 @@
|
|||
* window_move records WM-assigned x,y in the view struct.
|
||||
* Phase 56: prop_set/get_wm_state persist WM state (workspace, miniaturized,
|
||||
* shaded, etc.) in the view struct so wWindowGetSavedState works correctly.
|
||||
* Phase 57: icccm_set/get/free_command store WM_COMMAND in the view struct;
|
||||
* misc.c getCommandForWindow uses the vtable on the Wayland path.
|
||||
*/
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
|
|
@ -92,6 +94,8 @@ struct wl_toplevel_view {
|
|||
int x, y; /* Phase 55: WM-assigned position */
|
||||
long *wm_state; /* Phase 56: saved WM state or NULL */
|
||||
int wm_state_n; /* Phase 56: element count */
|
||||
char **wm_command; /* Phase 57: WM_COMMAND argv or NULL */
|
||||
int wm_command_n; /* Phase 57: argument count */
|
||||
struct wl_list link; /* wl_state.toplevel_list */
|
||||
};
|
||||
|
||||
|
|
@ -281,6 +285,12 @@ handle_toplevel_destroy(struct wl_listener *listener, void *data)
|
|||
wl_list_remove(&view->link);
|
||||
wl_state.managed_surface_count--;
|
||||
if (view->wm_state) wfree(view->wm_state); /* Phase 56 */
|
||||
if (view->wm_command) { /* Phase 57 */
|
||||
int ci;
|
||||
for (ci = 0; ci < view->wm_command_n; ci++)
|
||||
wfree(view->wm_command[ci]);
|
||||
wfree(view->wm_command);
|
||||
}
|
||||
wfree(view);
|
||||
}
|
||||
|
||||
|
|
@ -1064,9 +1074,50 @@ wl_coords_translate(WNativeWindow src, WNativeWindow dst,
|
|||
static void wl_icccm_set_wm_hints(WNativeWindow win, const WWMHints *hints) { (void)win; (void)hints; }
|
||||
static void wl_icccm_set_class_hint(WNativeWindow win, const char *wm_class, const char *wm_instance) { (void)win; (void)wm_class; (void)wm_instance; }
|
||||
static void wl_icccm_set_class_hint_if_absent(WNativeWindow win, const char *wm_class, const char *wm_instance) { (void)win; (void)wm_class; (void)wm_instance; }
|
||||
static void wl_icccm_set_command(WNativeWindow win, char **argv, int argc) { (void)win; (void)argv; (void)argc; }
|
||||
static int wl_icccm_get_command(WNativeWindow win, char ***argv_out, int *argc_out) { (void)win; *argv_out = NULL; *argc_out = 0; return 0; }
|
||||
static void wl_icccm_free_command(char **argv) { (void)argv; }
|
||||
static void
|
||||
wl_icccm_set_command(WNativeWindow win, char **argv, int argc)
|
||||
{
|
||||
/* Phase 57: store WM_COMMAND in the view struct. */
|
||||
struct wl_toplevel_view *v = wl_find_view_by_id(win);
|
||||
int i;
|
||||
if (!v || !argv || argc <= 0) return;
|
||||
/* free previous command if any */
|
||||
if (v->wm_command) {
|
||||
for (i = 0; i < v->wm_command_n; i++) wfree(v->wm_command[i]);
|
||||
wfree(v->wm_command);
|
||||
}
|
||||
v->wm_command = wmalloc((size_t)argc * sizeof(char *));
|
||||
for (i = 0; i < argc; i++)
|
||||
v->wm_command[i] = wstrdup(argv[i] ? argv[i] : "");
|
||||
v->wm_command_n = argc;
|
||||
}
|
||||
|
||||
static int
|
||||
wl_icccm_get_command(WNativeWindow win, char ***argv_out, int *argc_out)
|
||||
{
|
||||
/* Phase 57: return a NULL-terminated copy of the stored WM_COMMAND.
|
||||
* Caller frees with wl_icccm_free_command. */
|
||||
struct wl_toplevel_view *v = wl_find_view_by_id(win);
|
||||
int i;
|
||||
if (!v || !v->wm_command) { *argv_out = NULL; *argc_out = 0; return 0; }
|
||||
/* Allocate n+1 entries (NULL-terminated for free_command iteration). */
|
||||
*argv_out = wmalloc((size_t)(v->wm_command_n + 1) * sizeof(char *));
|
||||
for (i = 0; i < v->wm_command_n; i++)
|
||||
(*argv_out)[i] = wstrdup(v->wm_command[i]);
|
||||
(*argv_out)[v->wm_command_n] = NULL;
|
||||
*argc_out = v->wm_command_n;
|
||||
return 1;
|
||||
}
|
||||
|
||||
static void
|
||||
wl_icccm_free_command(char **argv)
|
||||
{
|
||||
/* Phase 57: free NULL-terminated argv returned by wl_icccm_get_command. */
|
||||
int i;
|
||||
if (!argv) return;
|
||||
for (i = 0; argv[i] != NULL; i++) wfree(argv[i]);
|
||||
wfree(argv);
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------------ */
|
||||
/* Fake leader */
|
||||
|
|
|
|||
17
src/misc.c
17
src/misc.c
|
|
@ -1072,7 +1072,22 @@ static char *getCommandForWindow(Window win, int elements)
|
|||
char **argv, *command = NULL;
|
||||
int argc;
|
||||
|
||||
if (!dpy) return NULL; /* Wayland: no X11 WM_COMMAND property */
|
||||
if (!dpy) {
|
||||
/* Wayland: read WM_COMMAND from the vtable-backed store. */
|
||||
if (!wm_backend->icccm_get_command((WNativeWindow)win, &argv, &argc))
|
||||
return NULL;
|
||||
if (argc > 0 && argv != NULL) {
|
||||
if (elements == 0)
|
||||
elements = argc;
|
||||
command = wtokenjoin(argv, WMIN(argc, elements));
|
||||
if (command[0] == 0) {
|
||||
wfree(command);
|
||||
command = NULL;
|
||||
}
|
||||
}
|
||||
wm_backend->icccm_free_command(argv);
|
||||
return command;
|
||||
}
|
||||
|
||||
if (XGetCommand(dpy, win, &argv, &argc)) {
|
||||
if (argc > 0 && argv != NULL) {
|
||||
|
|
|
|||
Loading…
Reference in New Issue