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.
|
* window_move records WM-assigned x,y in the view struct.
|
||||||
* Phase 56: prop_set/get_wm_state persist WM state (workspace, miniaturized,
|
* Phase 56: prop_set/get_wm_state persist WM state (workspace, miniaturized,
|
||||||
* shaded, etc.) in the view struct so wWindowGetSavedState works correctly.
|
* 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
|
#ifdef HAVE_CONFIG_H
|
||||||
|
|
@ -92,6 +94,8 @@ struct wl_toplevel_view {
|
||||||
int x, y; /* Phase 55: WM-assigned position */
|
int x, y; /* Phase 55: WM-assigned position */
|
||||||
long *wm_state; /* Phase 56: saved WM state or NULL */
|
long *wm_state; /* Phase 56: saved WM state or NULL */
|
||||||
int wm_state_n; /* Phase 56: element count */
|
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 */
|
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_list_remove(&view->link);
|
||||||
wl_state.managed_surface_count--;
|
wl_state.managed_surface_count--;
|
||||||
if (view->wm_state) wfree(view->wm_state); /* Phase 56 */
|
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);
|
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_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(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_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 void
|
||||||
static int wl_icccm_get_command(WNativeWindow win, char ***argv_out, int *argc_out) { (void)win; *argv_out = NULL; *argc_out = 0; return 0; }
|
wl_icccm_set_command(WNativeWindow win, char **argv, int argc)
|
||||||
static void wl_icccm_free_command(char **argv) { (void)argv; }
|
{
|
||||||
|
/* 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 */
|
/* 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;
|
char **argv, *command = NULL;
|
||||||
int argc;
|
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 (XGetCommand(dpy, win, &argv, &argc)) {
|
||||||
if (argc > 0 && argv != NULL) {
|
if (argc > 0 && argv != NULL) {
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue