1
0
mirror of https://github.com/gryf/wmaker.git synced 2026-06-18 16:35:24 +02:00

wmaker: dynamic vim-like window marking feature

This patch is adding vim-like window marking, like in i3.
A window can be dynamically assigned a mark label.
Then a marked window can be pulled or jumped to.
Or the current focused window can be swapped with a marked window.

The mark label appears in the Window List in between the window
title and the workspace name.

Those new options in WindowMaker conf file are used to control
the actions: MarkSetKey, MarkUnsetKey, MarkBringKey, MarkJumpKey
and MarkSwapKey.

Those actions are set to None by default.
This commit is contained in:
David Maciejak
2026-03-30 22:24:42 -04:00
committed by Carlos R. Mafra
parent ac1fa7fc6d
commit 26a296db23
13 changed files with 326 additions and 62 deletions
+59 -1
View File
@@ -75,6 +75,7 @@
#include "startup.h"
#include "winmenu.h"
#include "osdep.h"
#include "switchmenu.h"
#ifdef USE_MWM_HINTS
# include "motif.h"
@@ -200,6 +201,10 @@ void wWindowDestroy(WWindow *wwin)
}
}
/* clean up any mark assigned to this window */
if (wwin->mark_key_label != NULL)
wWindowUnsetMark(wwin);
if (wwin->fake_group && wwin->fake_group->retainCount > 0) {
wwin->fake_group->retainCount--;
if (wwin->fake_group->retainCount == 0 && wwin->fake_group->leader != None) {
@@ -1006,8 +1011,17 @@ WWindow *wManageWindow(WScreen *scr, Window window)
}
}
if (wstate != NULL)
/* restore mark: prefer session state, fall back to warm-restart hint */
if (win_state != NULL && win_state->state->mark_key != NULL)
wWindowSetMark(wwin, win_state->state->mark_key);
else if (wstate != NULL && wstate->mark_key != NULL)
wWindowSetMark(wwin, wstate->mark_key);
if (wstate != NULL) {
if (wstate->mark_key != NULL)
wfree(wstate->mark_key);
wfree(wstate);
}
}
/* don't let transients start miniaturized if their owners are not */
@@ -2527,6 +2541,14 @@ void wWindowSaveState(WWindow *wwin)
XChangeProperty(dpy, wwin->client_win, w_global.atom.wmaker.state,
w_global.atom.wmaker.state, 32, PropModeReplace, (unsigned char *)data, 10);
if (wwin->mark_key_label != NULL)
XChangeProperty(dpy, wwin->client_win, w_global.atom.wmaker.mark_key,
XA_STRING, 8, PropModeReplace,
(unsigned char *)wwin->mark_key_label,
strlen(wwin->mark_key_label));
else
XDeleteProperty(dpy, wwin->client_win, w_global.atom.wmaker.mark_key);
}
static int getSavedState(Window window, WSavedState ** state)
@@ -2536,6 +2558,7 @@ static int getSavedState(Window window, WSavedState ** state)
unsigned long nitems_ret;
unsigned long bytes_after_ret;
long *data;
unsigned char *mk_data = NULL;
if (XGetWindowProperty(dpy, window, w_global.atom.wmaker.state, 0, 10,
True, w_global.atom.wmaker.state,
@@ -2563,6 +2586,15 @@ static int getSavedState(Window window, WSavedState ** state)
XFree(data);
(*state)->mark_key = NULL;
if (XGetWindowProperty(dpy, window, w_global.atom.wmaker.mark_key, 0, 256,
True, XA_STRING, &type_ret, &fmt_ret, &nitems_ret, &bytes_after_ret,
&mk_data) == Success && mk_data && nitems_ret > 0 && type_ret == XA_STRING)
(*state)->mark_key = wstrdup((char *)mk_data);
if (mk_data)
XFree(mk_data);
return 1;
}
@@ -2889,6 +2921,9 @@ static void release_wwindowstate(WWindowState *wstate)
if (wstate->command)
wfree(wstate->command);
if (wstate->state && wstate->state->mark_key)
wfree(wstate->state->mark_key);
wfree(wstate->state);
wfree(wstate);
}
@@ -2902,6 +2937,29 @@ void wWindowSetOmnipresent(WWindow *wwin, Bool flag)
WMPostNotificationName(WMNChangedState, wwin, "omnipresent");
}
void wWindowSetMark(WWindow *wwin, const char *label)
{
/* Remove any previous mark first */
if (wwin->mark_key_label != NULL)
wWindowUnsetMark(wwin);
wwin->mark_key_label = wstrdup(label);
UpdateSwitchMenu(wwin->screen_ptr, wwin, ACTION_CHANGE);
}
void wWindowUnsetMark(WWindow *wwin)
{
if (wwin->mark_key_label == NULL)
return;
wfree(wwin->mark_key_label);
wwin->mark_key_label = NULL;
UpdateSwitchMenu(wwin->screen_ptr, wwin, ACTION_CHANGE);
}
static void resizebarMouseDown(WCoreWindow *sender, void *data, XEvent *event)
{
WWindow *wwin = data;