diff --git a/.config/suckless/dwm/Makefile b/.config/suckless/dwm/Makefile index a166452..c930324 100644 --- a/.config/suckless/dwm/Makefile +++ b/.config/suckless/dwm/Makefile @@ -48,6 +48,7 @@ install: all ifdef YAJLLIBS cp -f dwm-msg ${DESTDIR}${PREFIX}/bin endif + cp -f patch/dwmc ${DESTDIR}${PREFIX}/bin chmod 755 ${DESTDIR}${PREFIX}/bin/dwm ifdef YAJLLIBS chmod 755 ${DESTDIR}${PREFIX}/bin/dwm-msg @@ -55,13 +56,9 @@ endif mkdir -p ${DESTDIR}${MANPREFIX}/man1 sed "s/VERSION/${VERSION}/g" < dwm.1 > ${DESTDIR}${MANPREFIX}/man1/dwm.1 chmod 644 ${DESTDIR}${MANPREFIX}/man1/dwm.1 - mkdir -p ${DESTDIR}${PREFIX}/share/xsessions - test -f ${DESTDIR}${PREFIX}/share/xsessions/dwm.desktop || cp -n dwm.desktop ${DESTDIR}${PREFIX}/share/xsessions - chmod 644 ${DESTDIR}${PREFIX}/share/xsessions/dwm.desktop uninstall: rm -f ${DESTDIR}${PREFIX}/bin/dwm\ - ${DESTDIR}${MANPREFIX}/man1/dwm.1\ - ${DESTDIR}${PREFIX}/share/xsessions/dwm.desktop + ${DESTDIR}${MANPREFIX}/man1/dwm.1 .PHONY: all clean dist install uninstall diff --git a/.config/suckless/dwm/README.md b/.config/suckless/dwm/README.md index 9a6eeb4..a0cc5f9 100644 --- a/.config/suckless/dwm/README.md +++ b/.config/suckless/dwm/README.md @@ -6,36 +6,46 @@ This build of dwm was generated using [dwm-flexipatch](https://github.com/bakkeb The patches used are listed below: -- bar_dwmblocks -- bar_ltsymbol -- bar_status -- bar_statusbutton -- bar_statuscmd -- bar_status2d -- bar_status2d_xrdb_termcolors -- bar_tags -- bar_hidevacanttags -- center -- cool_autostart -- fakefullscreen_client -- focusdir -- focusfollowmouse -- monoclesymbol -- noborder -- nodmenu -- no_transparent_borders -- on_empty_keys -- pertag -- restartsig -- rotatestack -- scratchpads -- scratchpads_keep_position_and_size -- seamless_restart -- shiftboth -- shiftview_clients -- tapresize -- toggletag -- transfer -- xrdb -- tile_layout -- monocle_layout +- BAR_DWMBLOCKS_PATCH +- BAR_LTSYMBOL_PATCH +- BAR_STATUS_PATCH +- BAR_STATUSBUTTON_PATCH +- BAR_STATUSCMD_PATCH +- BAR_STATUS2D_PATCH +- BAR_STATUS2D_XRDB_TERMCOLORS_PATCH +- BAR_TAGS_PATCH +- BAR_BORDER_PATCH +- BAR_CENTEREDWINDOWNAME_PATCH +- BAR_EWMHTAGS_PATCH +- BAR_HEIGHT_PATCH +- BAR_HIDEVACANTTAGS_PATCH +- BAR_HOLDBAR_PATCH +- BAR_STATUSPADDING_PATCH +- CENTER_PATCH +- COOL_AUTOSTART_PATCH +- DWMC_PATCH +- FAKEFULLSCREEN_CLIENT_PATCH +- FOCUSDIR_PATCH +- FOCUSONCLICK_PATCH +- KILLUNSEL_PATCH +- MONOCLESYMBOL_PATCH +- NOBORDER_PATCH +- NODMENU_PATCH +- NO_TRANSPARENT_BORDERS_PATCH +- ON_EMPTY_KEYS_PATCH +- PERTAG_PATCH +- RESTARTSIG_PATCH +- ROTATESTACK_PATCH +- SAVEFLOATS_PATCH +- SCRATCHPADS_PATCH +- SCRATCHPADS_KEEP_POSITION_AND_SIZE_PATCH +- SEAMLESS_RESTART_PATCH +- SHIFTBOTH_PATCH +- SHIFTVIEW_CLIENTS_PATCH +- SWITCHTAG_PATCH +- TAPRESIZE_PATCH +- TOGGLETAG_PATCH +- TRANSFER_PATCH +- XRDB_PATCH +- TILE_LAYOUT +- MONOCLE_LAYOUT diff --git a/.config/suckless/dwm/config.h b/.config/suckless/dwm/config.h index c3cd44c..e4b279a 100644 --- a/.config/suckless/dwm/config.h +++ b/.config/suckless/dwm/config.h @@ -1,81 +1,91 @@ /* See LICENSE file for copyright and license details. */ #include -static const unsigned int borderpx = 1; /* border pixel of windows */ -static const unsigned int snap = 32; /* snap pixel */ -static const int showbar = 1; /* 0 means no bar */ -static const int topbar = 0; /* 0 means bottom bar */ -static const int statusmon = 'A'; -static const char buttonbar[] = " "; +/* appearance */ +static const unsigned int borderpx = 1; /* border pixel of windows */ +/* This allows the bar border size to be explicitly set separately from borderpx. + * If left as 0 then it will default to the borderpx value of the monitor and will + * automatically update with setborderpx. */ +static const unsigned int barborderpx = 0; /* border pixel of bar */ +static const unsigned int snap = 32; /* snap pixel */ +static const int showbar = 0; /* 0 means no bar */ +static const int topbar = 0; /* 0 means bottom bar */ +static const int bar_height = 0; /* 0 means derive from font, >= 1 explicit height */ +static const int focusonwheel = 0; +/* Status is to be shown on: -1 (all monitors), 0 (a specific monitor by index), 'A' (active monitor) */ +static const int statusmon = 'A'; +static const int horizpadbar = 2; /* horizontal padding for statusbar */ +static const int vertpadbar = 0; /* vertical padding for statusbar */ +static const char buttonbar[] = " "; /* Indicators: see patch/bar_indicators.h for options */ -static int tagindicatortype = INDICATOR_NONE; -static int tiledindicatortype = INDICATOR_NONE; -static int floatindicatortype = INDICATOR_TOP_LEFT_SQUARE; -static int fakefsindicatortype = INDICATOR_PLUS; -static int floatfakefsindicatortype = INDICATOR_PLUS_AND_LARGER_SQUARE; -// static const char *fonts[] = { "JetBrainsMono NF DWM:size=9" }; -static const char *fonts[] = { "CaskaydiaCove NF :pixelsize=12" }; +static int tagindicatortype = INDICATOR_NONE; +static int tiledindicatortype = INDICATOR_NONE; +static int floatindicatortype = INDICATOR_TOP_LEFT_SQUARE; +static int fakefsindicatortype = INDICATOR_PLUS; +static int floatfakefsindicatortype = INDICATOR_PLUS_AND_LARGER_SQUARE; +static const char *fonts[] = { "CaskaydiaCove NF :pixelsize=12" }; +static const char dmenufont[] = "monospace:size=10"; -static char c000000[] = "#000000"; // placeholder value +static char c000000[] = "#000000"; // placeholder value -static char normfgcolor[] = "#bbbbbb"; -static char normbgcolor[] = "#222222"; -static char normbordercolor[] = "#444444"; -static char normfloatcolor[] = "#db8fd9"; +static char normfgcolor[] = "#bbbbbb"; +static char normbgcolor[] = "#222222"; +static char normbordercolor[] = "#444444"; +static char normfloatcolor[] = "#db8fd9"; -static char selfgcolor[] = "#eeeeee"; -static char selbgcolor[] = "#88c096"; -static char selbordercolor[] = "#88c096"; -static char selfloatcolor[] = "#88c096"; +static char selfgcolor[] = "#eeeeee"; +static char selbgcolor[] = "#005577"; +static char selbordercolor[] = "#005577"; +static char selfloatcolor[] = "#005577"; -static char titlenormfgcolor[] = "#bbbbbb"; -static char titlenormbgcolor[] = "#222222"; -static char titlenormbordercolor[] = "#444444"; -static char titlenormfloatcolor[] = "#db8fd9"; +static char titlenormfgcolor[] = "#bbbbbb"; +static char titlenormbgcolor[] = "#222222"; +static char titlenormbordercolor[] = "#444444"; +static char titlenormfloatcolor[] = "#db8fd9"; -static char titleselfgcolor[] = "#eeeeee"; -static char titleselbgcolor[] = "#88c096"; -static char titleselbordercolor[] = "#88c096"; -static char titleselfloatcolor[] = "#88c096"; +static char titleselfgcolor[] = "#eeeeee"; +static char titleselbgcolor[] = "#005577"; +static char titleselbordercolor[] = "#005577"; +static char titleselfloatcolor[] = "#005577"; -static char tagsnormfgcolor[] = "#bbbbbb"; -static char tagsnormbgcolor[] = "#222222"; -static char tagsnormbordercolor[] = "#444444"; -static char tagsnormfloatcolor[] = "#db8fd9"; +static char tagsnormfgcolor[] = "#bbbbbb"; +static char tagsnormbgcolor[] = "#222222"; +static char tagsnormbordercolor[] = "#444444"; +static char tagsnormfloatcolor[] = "#db8fd9"; -static char tagsselfgcolor[] = "#eeeeee"; -static char tagsselbgcolor[] = "#88c096"; -static char tagsselbordercolor[] = "#88c096"; -static char tagsselfloatcolor[] = "#88c096"; +static char tagsselfgcolor[] = "#eeeeee"; +static char tagsselbgcolor[] = "#005577"; +static char tagsselbordercolor[] = "#005577"; +static char tagsselfloatcolor[] = "#005577"; -static char hidnormfgcolor[] = "#88c096"; -static char hidselfgcolor[] = "#227799"; -static char hidnormbgcolor[] = "#222222"; -static char hidselbgcolor[] = "#222222"; +static char hidnormfgcolor[] = "#005577"; +static char hidselfgcolor[] = "#227799"; +static char hidnormbgcolor[] = "#222222"; +static char hidselbgcolor[] = "#222222"; -static char urgfgcolor[] = "#bbbbbb"; -static char urgbgcolor[] = "#222222"; -static char urgbordercolor[] = "#ff0000"; -static char urgfloatcolor[] = "#db8fd9"; +static char urgfgcolor[] = "#bbbbbb"; +static char urgbgcolor[] = "#222222"; +static char urgbordercolor[] = "#ff0000"; +static char urgfloatcolor[] = "#db8fd9"; static char *colors[][ColCount] = { /* fg bg border float */ - [SchemeNorm] = { normfgcolor, normbgcolor, normbordercolor, normfloatcolor }, - [SchemeSel] = { selfgcolor, selbgcolor, selbordercolor, selfloatcolor }, - [SchemeTitleNorm] = { titlenormfgcolor, titlenormbgcolor, titlenormbordercolor, titlenormfloatcolor }, - [SchemeTitleSel] = { titleselfgcolor, titleselbgcolor, titleselbordercolor, titleselfloatcolor }, - [SchemeTagsNorm] = { tagsnormfgcolor, tagsnormbgcolor, tagsnormbordercolor, tagsnormfloatcolor }, - [SchemeTagsSel] = { tagsselfgcolor, tagsselbgcolor, tagsselbordercolor, tagsselfloatcolor }, - [SchemeHidNorm] = { hidnormfgcolor, hidnormbgcolor, c000000, c000000 }, - [SchemeHidSel] = { hidselfgcolor, hidselbgcolor, c000000, c000000 }, - [SchemeUrg] = { urgfgcolor, urgbgcolor, urgbordercolor, urgfloatcolor }, + [SchemeNorm] = { normfgcolor, normbgcolor, normbordercolor, normfloatcolor }, + [SchemeSel] = { selfgcolor, selbgcolor, selbordercolor, selfloatcolor }, + [SchemeTitleNorm] = { titlenormfgcolor, titlenormbgcolor, titlenormbordercolor, titlenormfloatcolor }, + [SchemeTitleSel] = { titleselfgcolor, titleselbgcolor, titleselbordercolor, titleselfloatcolor }, + [SchemeTagsNorm] = { tagsnormfgcolor, tagsnormbgcolor, tagsnormbordercolor, tagsnormfloatcolor }, + [SchemeTagsSel] = { tagsselfgcolor, tagsselbgcolor, tagsselbordercolor, tagsselfloatcolor }, + [SchemeHidNorm] = { hidnormfgcolor, hidnormbgcolor, c000000, c000000 }, + [SchemeHidSel] = { hidselfgcolor, hidselbgcolor, c000000, c000000 }, + [SchemeUrg] = { urgfgcolor, urgbgcolor, urgbordercolor, urgfloatcolor }, }; static const char *const autostart[] = { // "st", NULL, "dwmblocks", NULL, - NULL + NULL /* terminate */ }; const char *spcmd1[] = {"st", "-n", "spterm", "-g", "120x28", NULL }; @@ -92,6 +102,33 @@ static Sp scratchpads[] = { {"spnotes", spcmd5}, }; +/* Tags + * In a traditional dwm the number of tags in use can be changed simply by changing the number + * of strings in the tags array. This build does things a bit different which has some added + * benefits. If you need to change the number of tags here then change the NUMTAGS macro in dwm.c. + * + * Examples: + * + * 1) static char *tagicons[][NUMTAGS*2] = { + * [DEFAULT_TAGS] = { "1", "2", "3", "4", "5", "6", "7", "8", "9", "A", "B", "C", "D", "E", "F", "G", "H", "I" }, + * } + * + * 2) static char *tagicons[][1] = { + * [DEFAULT_TAGS] = { "•" }, + * } + * + * The first example would result in the tags on the first monitor to be 1 through 9, while the + * tags for the second monitor would be named A through I. A third monitor would start again at + * 1 through 9 while the tags on a fourth monitor would also be named A through I. Note the tags + * count of NUMTAGS*2 in the array initialiser which defines how many tag text / icon exists in + * the array. This can be changed to *3 to add separate icons for a third monitor. + * + * For the second example each tag would be represented as a bullet point. Both cases work the + * same from a technical standpoint - the icon index is derived from the tag index and the monitor + * index. If the icon index is is greater than the number of tag icons then it will wrap around + * until it an icon matches. Similarly if there are two tag icons then it would alternate between + * them. This works seamlessly with alternative tags and alttagsdecoration patches. + */ static char *tagicons[][NUMTAGS] = { [DEFAULT_TAGS] = { "1", "2", "3", "4", "5", "6", "7", "8", "9" }, @@ -99,13 +136,43 @@ static char *tagicons[][NUMTAGS] = [ALT_TAGS_DECORATION] = { "<1>", "<2>", "<3>", "<4>", "<5>", "<6>", "<7>", "<8>", "<9>" }, }; +/* There are two options when it comes to per-client rules: + * - a typical struct table or + * - using the RULE macro + * + * A traditional struct table looks like this: + * // class instance title wintype tags mask isfloating monitor + * { "Gimp", NULL, NULL, NULL, 1 << 4, 0, -1 }, + * { "Firefox", NULL, NULL, NULL, 1 << 7, 0, -1 }, + * + * The RULE macro has the default values set for each field allowing you to only + * specify the values that are relevant for your rule, e.g. + * + * RULE(.class = "Gimp", .tags = 1 << 4) + * RULE(.class = "Firefox", .tags = 1 << 7) + * + * Refer to the Rule struct definition for the list of available fields depending on + * the patches you enable. + */ static const Rule rules[] = { + /* xprop(1): + * WM_CLASS(STRING) = instance, class + * WM_NAME(STRING) = title + * WM_WINDOW_ROLE(STRING) = role + * _NET_WM_WINDOW_TYPE(ATOM) = wintype + */ RULE(.wintype = WTYPE "DIALOG", .isfloating = 1) RULE(.wintype = WTYPE "UTILITY", .isfloating = 1) RULE(.wintype = WTYPE "TOOLBAR", .isfloating = 1) RULE(.wintype = WTYPE "SPLASH", .isfloating = 1) // RULE(.class = "Gimp", .tags = 1 << 4) - // RULE(.class = "Firefox", .tags = 1 << 7) + RULE(.instance = "st",.class = "St", .title = "~", .tags = 1, .switchtag = 3) + RULE(.class = "firefox", .tags = 1 << 1, .switchtag = 3) + RULE(.title = "nvim", .tags = 1 << 2, .switchtag = 3) + RULE(.title = "lf", .tags = 1 << 3, .switchtag = 3) + RULE(.class = "mpv", .tags = 1 << 4, .switchtag = 3) + RULE(.title = "newsboat", .tags = 1 << 5, .switchtag = 3) + RULE(.class = "Gimp", .tags = 1 << 8, .switchtag = 3) RULE(.instance = "spterm", .tags = SPTAG(0), .isfloating = 1) RULE(.instance = "spcalc", .tags = SPTAG(1), .isfloating = 1) RULE(.class = "Qalculate-gtk", .tags = SPTAG(2), .isfloating = 1) @@ -113,35 +180,50 @@ static const Rule rules[] = { RULE(.instance = "spnotes", .tags = SPTAG(4), .isfloating = 1) RULE(.instance = "dictionary", .isfloating = 1) RULE(.class = "volume-ui", .isfloating = 1) + RULE(.instance = "spterm", .tags = SPTAG(0), .isfloating = 1) }; +/* Bar rules allow you to configure what is shown where on the bar, as well as + * introducing your own bar modules. + * + * monitor: + * -1 show on all monitors + * 0 show on monitor 0 + * 'A' show on active monitor (i.e. focused / selected) (or just -1 for active?) + * bar - bar index, 0 is default, 1 is extrabar + * alignment - how the module is aligned compared to other modules + * widthfunc, drawfunc, clickfunc - providing bar module width, draw and click functions + * name - does nothing, intended for visual clue and for logging / debugging + */ static const BarRule barrules[] = { - /* monitor bar alignment widthfunc drawfunc clickfunc hoverfunc name */ - { -1, 0, BAR_ALIGN_LEFT, width_stbutton, draw_stbutton, click_stbutton, NULL, "statusbutton" }, - { -1, 0, BAR_ALIGN_LEFT, width_tags, draw_tags, click_tags, hover_tags, "tags" }, - { -1, 0, BAR_ALIGN_LEFT, width_ltsymbol, draw_ltsymbol, click_ltsymbol, NULL, "layout" }, - { statusmon, 0, BAR_ALIGN_RIGHT, width_status2d, draw_status2d, click_statuscmd, NULL, "status2d" }, + /* monitor bar alignment widthfunc drawfunc clickfunc hoverfunc name */ + { -1, 0, BAR_ALIGN_LEFT, width_stbutton, draw_stbutton, click_stbutton, NULL, "statusbutton" }, + { -1, 0, BAR_ALIGN_LEFT, width_tags, draw_tags, click_tags, hover_tags, "tags" }, + { -1, 0, BAR_ALIGN_LEFT, width_ltsymbol, draw_ltsymbol, click_ltsymbol, NULL, "layout" }, + { statusmon, 0, BAR_ALIGN_RIGHT, width_status2d, draw_status2d, click_statuscmd, NULL, "status2d" }, }; /* layout(s) */ -static const float mfact = 0.50; -static const int nmaster = 1; -static const int resizehints = 0; -static const int lockfullscreen = 1; +static const float mfact = 0.50; /* factor of master area size [0.05..0.95] */ +static const int nmaster = 1; /* number of clients in master area */ +static const int resizehints = 0; /* 1 means respect size hints in tiled resizals */ +static const int lockfullscreen = 1; /* 1 will force focus on the fullscreen window */ /* mouse scroll resize */ -static const int scrollsensetivity = 15; +static const int scrollsensetivity = 30; /* 1 means resize window by 1 pixel for each scroll event */ +/* resizemousescroll direction argument list */ static const int scrollargs[][2] = { /* width change height change */ { +scrollsensetivity, 0 }, { -scrollsensetivity, 0 }, - { 0, +scrollsensetivity }, - { 0, -scrollsensetivity }, + { 0, +scrollsensetivity }, + { 0, -scrollsensetivity }, }; static const Layout layouts[] = { + /* symbol arrange function */ { "󰙀", tile }, /* first entry is default */ - { "󰖲", NULL }, + { "󰖲", NULL }, /* no layout function means floating behavior */ { "󰖯", monocle }, }; @@ -149,116 +231,137 @@ static const Layout layouts[] = { #define MODKEY Mod4Mask #define ALTKEY Mod1Mask #define TAGKEYS(KEY,TAG) \ - { MODKEY, KEY, view, {.ui = 1 << TAG} }, \ - { MODKEY|ControlMask, KEY, toggleview, {.ui = 1 << TAG} }, \ - { MODKEY|ShiftMask, KEY, tag, {.ui = 1 << TAG} }, \ - { MODKEY|ControlMask|ShiftMask, KEY, toggletag, {.ui = 1 << TAG} }, + { MODKEY, KEY, view, {.ui = 1 << TAG} }, \ + { MODKEY|ControlMask, KEY, toggleview, {.ui = 1 << TAG} }, \ + { MODKEY|ShiftMask, KEY, tag, {.ui = 1 << TAG} }, \ + { MODKEY|ControlMask|ShiftMask, KEY, toggletag, {.ui = 1 << TAG} }, + +#define HOLDKEY 0xffeb // replace 0 with the keysym to activate holdbar /* helper for spawning shell commands in the pre dwm-5.0 fashion */ #define SHCMD(cmd) { .v = (const char*[]){ "/bin/sh", "-c", cmd, NULL } } -#define STATUSBAR "dwmblocks" +/* commands */ -static const char *termcmd[] = { "st", NULL }; static const char* dmenu_run_cmd[] = { "dmenu_run", "-bw", "2", "-i", "-W", "390", "-X", "961", "-Y", "15", "-l", "15", "-g", "3", NULL }; static const char* clipmenu_cmd[] = { "clipmenu", "-bw", "2", "-i", "-W", "290", "-X", "1061", "-Y", "15", "-l", "15", NULL }; +static const char* volume_ui_cmd[] = { "st", "-c", "volume-ui", "-g=80x15+353+20", "-e", "pulsemixer", NULL } ; + +/* This defines the name of the executable that handles the bar (used for signalling purposes) */ +#define STATUSBAR "dwmblocks" + static const Key on_empty_keys[] = { -/* modifier key function argument */ - { 0, XK_w, spawn, {.v = (const char*[]){ "firefox", NULL } } }, - { 0, XK_grave, spawn, {.v = (const char*[]){ "dmenunerdsymbols", NULL } } }, - { 0, XK_BackSpace, spawn, {.v = (const char*[]){ "sysact", NULL } } }, - { 0, XK_r, spawn, {.v = (const char*[]){ "st", "-e", "lf", NULL } } }, - { 0, XK_Return, spawn, {.v = (const char*[]){ "st", NULL } } }, - { 0, XK_d, spawn, {.v = dmenu_run_cmd } }, - { 0, XK_a, spawn, {.v = (const char*[]){ "dmenu_hub", NULL } } }, - { 0, XK_space, spawn, {.v = (const char*[]){ "dmenu_web", NULL } } }, - { 0, XK_n, spawn, {.v = (const char*[]){ "st", "-e", "nvim", NULL } } }, + /* modifier key function argument */ + {0, XK_w, spawn, {.v = (const char *[]){"firefox", NULL}}}, + {0, XK_grave, spawn, {.v = (const char *[]){"dmenunerdsymbols", NULL}}}, + {0, XK_BackSpace, spawn, {.v = (const char *[]){"sysact", NULL}}}, + {0, XK_r, spawn, {.v = (const char *[]){"st", "-e", "lf", NULL}}}, + {0, XK_Return, spawn, {.v = (const char *[]){"st", NULL}}}, + {0, XK_d, spawn, {.v = dmenu_run_cmd}}, + {0, XK_a, spawn, {.v = (const char *[]){"dmenu_hub", NULL}}}, + {0, XK_space, spawn, {.v = (const char *[]){"dmenu_web", NULL}}}, + {0, XK_n, spawn, {.v = (const char *[]){"st", "-e", "nvim", NULL}}}, }; static const Key keys[] = { - /* modifier key function argument */ - { 0,XF86XK_AudioMute, spawn, SHCMD("wpctl set-mute @DEFAULT_AUDIO_SINK@ toggle; pkill -RTMIN+8 dwmblocks") }, - { 0,XF86XK_AudioRaiseVolume, spawn, SHCMD("wpctl set-volume @DEFAULT_AUDIO_SINK@ 0%- && wpctl set-volume @DEFAULT_AUDIO_SINK@ 3%+; pkill -RTMIN+8 dwmblocks") }, - { 0,XF86XK_AudioLowerVolume, spawn, SHCMD("wpctl set-volume @DEFAULT_AUDIO_SINK@ 0%+ && wpctl set-volume @DEFAULT_AUDIO_SINK@ 3%-; pkill -RTMIN+8 dwmblocks") }, - { 0,XF86XK_AudioPrev, spawn, {.v = (const char*[]){ "mpc", "prev", NULL } } }, - { 0,XF86XK_AudioNext, spawn, {.v = (const char*[]){ "mpc", "next", NULL } } }, - { 0,XF86XK_AudioPause, spawn, {.v = (const char*[]){ "mpc", "pause", NULL } } }, - { 0,XF86XK_AudioPlay, spawn, {.v = (const char*[]){ "mpc", "play", NULL } } }, - { 0,XK_F7, spawn, {.v = clipmenu_cmd } }, - { 0,XF86XK_MonBrightnessUp, spawn, {.v = (const char*[]){ "xbacklight", "-inc", "15", NULL } } }, - { 0,XF86XK_MonBrightnessDown, spawn, {.v = (const char*[]){ "xbacklight", "-dec", "15", NULL } } }, - { 0, XK_Print, spawn, {.v = (const char*[]){ "maimpick", NULL } } }, - { MODKEY, XK_Print, spawn, {.v = (const char*[]){ "dmenurecord", NULL } } }, - { MODKEY|ShiftMask, XK_Delete, quit, {0} }, - { MODKEY, XK_Delete, quit, {1} }, - { MODKEY|ControlMask, XK_grave, setscratch, {.ui = 0 } }, - { MODKEY|ShiftMask, XK_grave, removescratch, {.ui = 0 } }, - { MODKEY, XK_0, view, {.ui = ~SPTAGMASK } }, - { MODKEY|ShiftMask, XK_0, tag, {.ui = ~SPTAGMASK } }, - TAGKEYS( XK_1, 0) - TAGKEYS( XK_2, 1) - TAGKEYS( XK_3, 2) - TAGKEYS( XK_4, 3) - TAGKEYS( XK_5, 4) - TAGKEYS( XK_6, 5) - TAGKEYS( XK_7, 6) - TAGKEYS( XK_8, 7) - TAGKEYS( XK_9, 8) + /* modifier key function argument */ + { 0,XF86XK_AudioMute, spawn,SHCMD("wpctl set-mute @DEFAULT_AUDIO_SINK@ toggle; pkill -RTMIN+8 dwmblocks") }, + { 0,XF86XK_AudioRaiseVolume,spawn,SHCMD("wpctl set-volume @DEFAULT_AUDIO_SINK@ 0%- && wpctl set-volume @DEFAULT_AUDIO_SINK@ 3%+; pkill -RTMIN+8 dwmblocks") }, + { 0,XF86XK_AudioLowerVolume,spawn,SHCMD("wpctl set-volume @DEFAULT_AUDIO_SINK@ 0%+ && wpctl set-volume @DEFAULT_AUDIO_SINK@ 3%-; pkill -RTMIN+8 dwmblocks") }, + { 0,XF86XK_AudioPrev, spawn, {.v = (const char*[]){ "mpc", "prev", NULL } } }, + { 0,XF86XK_AudioNext, spawn, {.v = (const char*[]){ "mpc", "next", NULL } } }, + { 0,XF86XK_AudioPause, spawn, {.v = (const char*[]){ "mpc", "pause", NULL } } }, + { 0,XF86XK_AudioPlay, spawn, {.v = (const char*[]){ "mpc", "play", NULL } } }, + { MODKEY|ShiftMask, XK_F5, xrdb, {.v = NULL } }, + { 0,XK_F7, spawn, {.v = clipmenu_cmd } }, + { 0,XF86XK_MonBrightnessUp, spawn, {.v = (const char*[]){ "xbacklight", "-inc", "15", NULL } } }, + { 0,XF86XK_MonBrightnessDown, spawn, {.v = (const char*[]){ "xbacklight", "-dec", "15", NULL } } }, + { 0, XK_Print, spawn, {.v = (const char*[]){ "maimpick", NULL } } }, + { MODKEY, XK_Print, spawn, {.v = (const char*[]){ "dmenurecord", NULL } } }, + { MODKEY|ShiftMask, XK_Delete, quit, {0} }, + { MODKEY, XK_Delete, quit, {1} }, + { MODKEY, XK_grave, togglescratch, {.ui = 0 } }, + { MODKEY|ControlMask, XK_grave, setscratch, {.ui = 0 } }, + { MODKEY|ShiftMask, XK_grave, removescratch, {.ui = 0 } }, + { MODKEY, XK_0, view, {.ui = ~SPTAGMASK } }, + { MODKEY|ShiftMask, XK_0, tag, {.ui = ~SPTAGMASK } }, + TAGKEYS( XK_1, 0) + TAGKEYS( XK_2, 1) + TAGKEYS( XK_3, 2) + TAGKEYS( XK_4, 3) + TAGKEYS( XK_5, 4) + TAGKEYS( XK_6, 5) + TAGKEYS( XK_7, 6) + TAGKEYS( XK_8, 7) + TAGKEYS( XK_9, 8) + { MODKEY, XK_equal, spawn, {.v = volume_ui_cmd } }, + { MODKEY, XK_minus, spawn, {.v = volume_ui_cmd } }, { MODKEY, XK_BackSpace, spawn, {.v = (const char*[]){ "sysact", NULL } } }, - { MODKEY|ShiftMask, XK_BackSpace, spawn, {.v = (const char*[]){ "sysact", NULL } } }, { MODKEY, XK_Tab, view, {0} }, { MODKEY, XK_q, killclient, {0} }, + { MODKEY|ShiftMask, XK_q, killunsel, {0} }, { MODKEY, XK_w, spawn, {.v = (const char*[]){ "firefox", NULL } } }, + { MODKEY, XK_e, spawn, {.v = (const char*[]){ "networkmanager_dmenu", NULL } } }, { MODKEY, XK_r, spawn, {.v = (const char*[]){ "st", "-e", "lf", NULL } } }, { MODKEY|ShiftMask, XK_r, spawn, {.v = (const char*[]){ "thunar", NULL } } }, - { MODKEY, XK_t, setlayout, {.v = &layouts[0]} }, // tiled - { MODKEY, XK_y, setlayout, {.v = &layouts[1]} }, // monocle - { MODKEY, XK_u, setlayout, {.v = &layouts[2]} }, // none + { MODKEY, XK_t, setlayout, {.v = &layouts[0]} }, + { MODKEY, XK_u, setlayout, {.v = &layouts[1]} }, + { MODKEY, XK_y, setlayout, {.v = &layouts[2]} }, + { MODKEY, XK_i, setlayout, {0} }, { MODKEY, XK_o, incnmaster, {.i = +1 } }, { MODKEY|ShiftMask, XK_o, incnmaster, {.i = -1 } }, { MODKEY, XK_a, spawn, {.v = (const char*[]){ "dmenu_hub", NULL } } }, { MODKEY, XK_d, spawn, {.v = dmenu_run_cmd } }, - { MODKEY, XK_f, togglefakefullscreen, {0} }, + { MODKEY, XK_f, togglefakefullscreen, {0} }, { MODKEY, XK_h, setmfact, {.f = -0.05} }, - { ALTKEY, XK_h, spawn, {.v = (const char*[]){ "dmenuhandler", NULL } } }, + { MODKEY, XK_j, focusstack, {.i = +1 } }, + { MODKEY, XK_k, focusstack, {.i = -1 } }, { MODKEY, XK_l, setmfact, {.f = +0.05} }, { ALTKEY, XK_l, spawn, {.v = (const char*[]){"dictionary", NULL } } }, { MODKEY|ShiftMask, XK_apostrophe, togglescratch, {.ui = 2 } }, { MODKEY, XK_apostrophe, togglescratch, {.ui = 1 } }, - { MODKEY, XK_Return, spawn, {.v = termcmd } }, + { MODKEY, XK_Return, spawn, {.v = (const char *[]){"st", NULL}}}, + { ALTKEY, XK_Return, spawn, {.v = (const char *[]){"st", "-c", "st", NULL}}}, { MODKEY|ShiftMask, XK_Return, togglescratch, {.ui = 0 } }, - { MODKEY, XK_m, togglescratch, {.ui = 3 } }, - { MODKEY, XK_comma, togglescratch, {.ui = 4 } }, { MODKEY, XK_x, transfer, {0} }, { MODKEY, XK_b, togglebar, {0} }, { MODKEY|ShiftMask, XK_b, spawn, {.v = (const char*[]){ "dmenu_web", "--add" , NULL } } }, { MODKEY, XK_n, spawn, {.v = (const char*[]){ "st", "-e", "nvim", NULL } } }, { MODKEY|ShiftMask, XK_n, spawn, {.v = (const char*[]){ "st", "-e", "newsboat", NULL } } }, - // { MODKEY, XK_m, spawn, {.v = (const char*[]){ "st", "-e", "ncmpcpp", NULL } } }, + { MODKEY, XK_m, togglescratch, {.ui = 3 } }, + { MODKEY, XK_comma, togglescratch, {.ui = 4 } }, + // { MODKEY, XK_comma, focusmon, {.i = -1 } }, + // { MODKEY, XK_period, focusmon, {.i = +1 } }, + // { MODKEY|ShiftMask, XK_comma, tagmon, {.i = -1 } }, + // { MODKEY|ShiftMask, XK_period, tagmon, {.i = +1 } }, + { MODKEY, XK_slash, zoom, {0} }, + { 0, HOLDKEY, holdbar, {0} }, { MODKEY, XK_space, spawn, {.v = (const char*[]){ "dmenu_web", NULL } } }, { MODKEY|ShiftMask, XK_space, togglefloating, {0} }, - { MODKEY, XK_Left, focusdir, {.i = 0 } }, - { MODKEY, XK_Right, focusdir, {.i = 1 } }, - { MODKEY, XK_Up, focusdir, {.i = 2 } }, - { MODKEY, XK_Down, focusdir, {.i = 3 } }, + { MODKEY, XK_Left, focusdir, {.i = 0 } }, // left + { MODKEY, XK_Right, focusdir, {.i = 1 } }, // right + { MODKEY, XK_Up, focusdir, {.i = 2 } }, // up + { MODKEY, XK_Down, focusdir, {.i = 3 } }, // down { MODKEY|ControlMask, XK_Up, rotatestack, {.i = +1 } }, { MODKEY|ControlMask, XK_Down, rotatestack, {.i = -1 } }, { MODKEY|Mod1Mask, XK_Left, shiftboth, { .i = -1 } }, { MODKEY|Mod1Mask, XK_Right, shiftboth, { .i = +1 } }, { MODKEY|ControlMask, XK_Left, shiftviewclients, { .i = -1 } }, { MODKEY|ControlMask, XK_Right, shiftviewclients, { .i = +1 } }, + }; /* button definitions */ /* click can be ClkTagBar, ClkLtSymbol, ClkStatusText, ClkWinTitle, ClkClientWin, or ClkRootWin */ static const Button buttons[] = { - /* click event mask button function argument */ - { ClkRootWin, 0, Button1, spawn, SHCMD("dunstctl close-all; killall dmenu") }, - { ClkRootWin, 0, Button3, spawn, SHCMD("dunstctl close-all; pgrep -x 'dmenu' > /dev/null && killall dmenu || dmenu_hub") }, + /* click event mask button function argument */ + { ClkRootWin, 0, Button1, spawn, SHCMD("dunstctl close-all; killall dmenu") }, + { ClkRootWin, 0, Button3, spawn, SHCMD("dunstctl close-all; pgrep -x 'dmenu' > /dev/null && killall dmenu || dmenu_hub") }, { ClkButton, 0, Button1, spawn, {.v = dmenu_run_cmd } }, { ClkButton, 0, Button3, spawn, {.v = (const char*[]){ "dmenu_hub", NULL } } }, { ClkLtSymbol, 0, Button1, setlayout, {0} }, { ClkLtSymbol, 0, Button3, setlayout, {.v = &layouts[2]} }, + { ClkWinTitle, 0, Button2, zoom, {0} }, { ClkStatusText, 0, Button1, sigstatusbar, {.i = 1 } }, { ClkStatusText, 0, Button2, sigstatusbar, {.i = 2 } }, { ClkStatusText, 0, Button3, sigstatusbar, {.i = 3 } }, @@ -278,3 +381,39 @@ static const Button buttons[] = { { ClkTagBar, MODKEY, Button1, tag, {0} }, { ClkTagBar, MODKEY, Button3, toggletag, {0} }, }; + +/* signal definitions */ +/* signum must be greater than 0 */ +/* trigger signals using `xsetroot -name "fsignal: [ ]"` */ +static const Signal signals[] = { + /* signum function */ + { "focusstack", focusstack }, + { "setmfact", setmfact }, + { "togglebar", togglebar }, + { "incnmaster", incnmaster }, + { "togglefloating", togglefloating }, + { "focusmon", focusmon }, + { "rotatestack", rotatestack }, + { "transfer", transfer }, + { "tagmon", tagmon }, + { "zoom", zoom }, + { "view", view }, + { "viewall", viewallex }, + { "viewex", viewex }, + { "toggleview", toggleview }, + { "shiftboth", shiftboth }, + { "shiftviewclients", shiftviewclients }, + { "toggleviewex", toggleviewex }, + { "tag", tag }, + { "tagall", tagallex }, + { "tagex", tagex }, + { "toggletag", toggletag }, + { "toggletagex", toggletagex }, + { "togglefakefullscreen", togglefakefullscreen }, + { "togglescratch", togglescratch }, + { "killclient", killclient }, + { "xrdb", xrdb }, + { "quit", quit }, + { "setlayout", setlayout }, + { "setlayoutex", setlayoutex }, +}; diff --git a/.config/suckless/dwm/config.mk b/.config/suckless/dwm/config.mk index 69b8092..d0bb5e6 100644 --- a/.config/suckless/dwm/config.mk +++ b/.config/suckless/dwm/config.mk @@ -1,5 +1,5 @@ # dwm version -VERSION = 6.4 +VERSION = 6.5 # Customize below to fit your system @@ -15,8 +15,8 @@ X11LIB = /usr/X11R6/lib #X11LIB = /usr/local/lib # Xinerama, comment if you don't want it -XINERAMALIBS = -lXinerama -XINERAMAFLAGS = -DXINERAMA +# XINERAMALIBS = -lXinerama +# XINERAMAFLAGS = -DXINERAMA # freetype FREETYPELIBS = -lfontconfig -lXft @@ -29,7 +29,7 @@ FREETYPEINC = /usr/include/freetype2 #KVMLIB = -lkvm # Uncomment this for the alpha patch and the winicon patch (BAR_ALPHA_PATCH, BAR_WINICON_PATCH) -XRENDER = -lXrender +#XRENDER = -lXrender # Uncomment this for the mdpcontrol patch / MDPCONTROL_PATCH #MPDCLIENT = -lmpdclient diff --git a/.config/suckless/dwm/drw.c b/.config/suckless/dwm/drw.c index 8e09a26..8f60447 100644 --- a/.config/suckless/dwm/drw.c +++ b/.config/suckless/dwm/drw.c @@ -8,7 +8,6 @@ #include "drw.h" #include "util.h" - #define UTF_INVALID 0xFFFD #define UTF_SIZ 4 @@ -17,7 +16,6 @@ static const unsigned char utfmask[UTF_SIZ + 1] = {0xC0, 0x80, 0xE0, 0xF0, 0xF8} static const long utfmin[UTF_SIZ + 1] = { 0, 0, 0x80, 0x800, 0x10000}; static const long utfmax[UTF_SIZ + 1] = {0x10FFFF, 0x7F, 0x7FF, 0xFFFF, 0x10FFFF}; - static long utf8decodebyte(const char c, size_t *i) { @@ -136,7 +134,6 @@ xfont_create(Drw *drw, const char *fontname, FcPattern *fontpattern) die("no font specified."); } - font = ecalloc(1, sizeof(Fnt)); font->xfont = xfont; font->pattern = pattern; @@ -235,7 +232,6 @@ drw_setscheme(Drw *drw, Clr *scm) drw->scheme = scm; } - void drw_rect(Drw *drw, int x, int y, unsigned int w, unsigned int h, int filled, int invert) { @@ -378,8 +374,6 @@ drw_text(Drw *drw, int x, int y, unsigned int w, unsigned int h, unsigned int lp return x + (render ? w : 0); } - - void drw_map(Drw *drw, Window win, int x, int y, unsigned int w, unsigned int h) { diff --git a/.config/suckless/dwm/drw.h b/.config/suckless/dwm/drw.h index d1f8cc0..4ff4870 100644 --- a/.config/suckless/dwm/drw.h +++ b/.config/suckless/dwm/drw.h @@ -1,6 +1,5 @@ /* See LICENSE file for copyright and license details. */ - typedef struct { Cursor cursor; } Cur; diff --git a/.config/suckless/dwm/dwm.c b/.config/suckless/dwm/dwm.c index 8218982..fb5370f 100644 --- a/.config/suckless/dwm/dwm.c +++ b/.config/suckless/dwm/dwm.c @@ -44,12 +44,8 @@ #include "drw.h" #include "util.h" - - #include - - /* macros */ #define Button6 6 #define Button7 7 @@ -99,6 +95,7 @@ enum { enum { NetSupported, NetWMName, NetWMState, NetWMCheck, NetWMFullscreen, NetActiveWindow, NetWMWindowType, + NetDesktopNames, NetDesktopViewport, NetNumberOfDesktops, NetCurrentDesktop, NetClientList, NetLast }; /* EWMH atoms */ @@ -142,7 +139,6 @@ enum { BAR_ALIGN_LAST }; /* bar alignment */ - typedef union { int i; unsigned int ui; @@ -194,17 +190,18 @@ typedef struct { const Arg arg; } Button; - typedef struct Client Client; struct Client { char name[256]; float mina, maxa; int x, y, w, h; + int sfx, sfy, sfw, sfh; /* stored float geometry, used on mode revert */ unsigned int idx; int oldx, oldy, oldw, oldh; int basew, baseh, incw, inch, maxw, maxh, minw, minh, hintsvalid; int bw, oldbw; unsigned int tags; + unsigned int switchtag; int isfixed, isfloating, isurgent, neverfocus, oldstate, isfullscreen; int fakefullscreen; int iscentered; @@ -221,13 +218,11 @@ typedef struct { const Arg arg; } Key; - typedef struct { const char *symbol; void (*arrange)(Monitor *); } Layout; - typedef struct Pertag Pertag; struct Monitor { char ltsymbol[16]; @@ -255,6 +250,7 @@ typedef struct { const char *title; const char *wintype; unsigned int tags; + int switchtag; int iscentered; int isfloating; int monitor; @@ -269,8 +265,7 @@ typedef struct { #define FAKEFULLSCREEN #define NOSWALLOW #define TERMINAL -#define SWITCHTAG - +#define SWITCHTAG , .switchtag = 1 /* function declarations */ static void applyrules(Client *c); @@ -295,7 +290,6 @@ static Monitor *dirtomon(int dir); static void drawbar(Monitor *m); static void drawbars(void); static void drawbarwin(Bar *bar); -static void enternotify(XEvent *e); static void expose(XEvent *e); static void focus(Client *c); static void focusin(XEvent *e); @@ -316,6 +310,7 @@ static void maprequest(XEvent *e); static void motionnotify(XEvent *e); static void movemouse(const Arg *arg); static Client *nexttiled(Client *c); +static int noborder(Client *c); static void pop(Client *c); static void propertynotify(XEvent *e); static void quit(const Arg *arg); @@ -386,14 +381,15 @@ static int (*xerrorxlib)(Display *, XErrorEvent *); static unsigned int numlockmask = 0; static void (*handler[LASTEvent]) (XEvent *) = { [ButtonPress] = buttonpress, + [ButtonRelease] = keyrelease, [ClientMessage] = clientmessage, [ConfigureRequest] = configurerequest, [ConfigureNotify] = configurenotify, [DestroyNotify] = destroynotify, - [EnterNotify] = enternotify, [Expose] = expose, [FocusIn] = focusin, [KeyPress] = keypress, + [KeyRelease] = keyrelease, [MappingNotify] = mappingnotify, [MapRequest] = maprequest, [MotionNotify] = motionnotify, @@ -426,6 +422,7 @@ applyrules(Client *c) const char *class, *instance; Atom wintype; unsigned int i; + unsigned int newtagset; const Rule *r; Monitor *m; XClassHint ch = { NULL, NULL }; @@ -438,7 +435,6 @@ applyrules(Client *c) instance = ch.res_name ? ch.res_name : broken; wintype = getatomprop(c, netatom[NetWMWindowType], XA_ATOM); - for (i = 0; i < LENGTH(rules); i++) { r = &rules[i]; if ((!r->title || strstr(c->name, r->title)) @@ -457,6 +453,27 @@ applyrules(Client *c) if (m) c->mon = m; + if (r->switchtag) + { + unfocus(selmon->sel, 1, NULL); + selmon = c->mon; + if (r->switchtag == 2 || r->switchtag == 4) + newtagset = c->mon->tagset[c->mon->seltags] ^ c->tags; + else + newtagset = c->tags; + + /* Switch to the client's tag, but only if that tag is not already shown */ + if (newtagset && !(c->tags & c->mon->tagset[c->mon->seltags])) { + if (r->switchtag == 3 || r->switchtag == 4) + c->switchtag = c->mon->tagset[c->mon->seltags]; + if (r->switchtag == 1 || r->switchtag == 3) { + view(&((Arg) { .ui = newtagset })); + } else { + c->mon->tagset[c->mon->seltags] = newtagset; + arrange(c->mon); + } + } + } } } if (ch.res_class) @@ -583,9 +600,9 @@ buttonpress(XEvent *e) BarArg carg = { 0, 0, 0, 0 }; click = ClkRootWin; - /* focus monitor if necessary */ if ((m = wintomon(ev->window)) && m != selmon + && (focusonwheel || (ev->button != Button4 && ev->button != Button5)) ) { unfocus(selmon->sel, 1, NULL); selmon = m; @@ -615,10 +632,9 @@ buttonpress(XEvent *e) } } - if (click == ClkRootWin && (c = wintoclient(ev->window))) { - focus(c); - restack(selmon); + if (focusonwheel || (ev->button != Button4 && ev->button != Button5)) + focus(c); XAllowEvents(dpy, ReplayPointer, CurrentTime); click = ClkClientWin; } @@ -653,7 +669,6 @@ cleanup(void) Layout foo = { "", NULL }; size_t i; - for (m = mons; m; m = m->next) persistmonitorstate(m); @@ -715,7 +730,6 @@ clientmessage(XEvent *e) XClientMessageEvent *cme = &e->xclient; Client *c = wintoclient(cme->window); - if (!c) return; if (cme->message_type == netatom[NetWMState]) { @@ -748,6 +762,13 @@ configure(Client *c) ce.width = c->w; ce.height = c->h; ce.border_width = c->bw; + + if (noborder(c)) { + ce.width += c->bw * 2; + ce.height += c->bw * 2; + ce.border_width = 0; + } + ce.above = None; ce.override_redirect = False; XSendEvent(dpy, c->win, False, StructureNotifyMask, (XEvent *)&ce); @@ -875,12 +896,11 @@ createmon(void) istopbar = !istopbar; bar->showbar = 1; bar->external = 0; - bar->borderpx = 0; + bar->borderpx = (barborderpx ? barborderpx : borderpx); bar->bh = bh + bar->borderpx * 2; bar->borderscheme = SchemeNorm; } - if (!(m->pertag = (Pertag *)calloc(1, sizeof(Pertag)))) die("fatal: could not malloc() %u bytes\n", sizeof(Pertag)); m->pertag->curtag = 1; @@ -892,8 +912,6 @@ createmon(void) /* init mfacts */ m->pertag->mfacts[i] = m->mfact; - - /* init layouts */ m->pertag->ltidxs[i][0] = m->lt[0]; m->pertag->ltidxs[i][1] = m->lt[1]; @@ -1096,25 +1114,6 @@ drawbarwin(Bar *bar) drw_map(drw, bar->win, 0, 0, bar->bw, bar->bh); } -void -enternotify(XEvent *e) -{ - Client *c; - Monitor *m; - XCrossingEvent *ev = &e->xcrossing; - - if ((ev->mode != NotifyNormal || ev->detail == NotifyInferior) && ev->window != root) - return; - c = wintoclient(ev->window); - m = c ? c->mon : wintomon(ev->window); - if (m != selmon) { - unfocus(selmon->sel, 1, c); - selmon = m; - } else if (!c || c == selmon->sel) - return; - focus(c); -} - void expose(XEvent *e) { @@ -1129,8 +1128,6 @@ expose(XEvent *e) void focus(Client *c) { - if (!c || !ISVISIBLE(c)) - c = getpointerclient(); if (!c || !ISVISIBLE(c)) for (c = selmon->stack; c && !ISVISIBLE(c); c = c->snext); if (selmon->sel && selmon->sel != c) @@ -1219,7 +1216,6 @@ getatomprop(Client *c, Atom prop, Atom req) unsigned char *p = NULL; Atom da, atom = None; - /* FIXME getatomprop should return the number of items and a pointer to * the stored data instead of this workaround */ if (XGetWindowProperty(dpy, c->win, prop, 0L, sizeof atom, False, req, @@ -1412,6 +1408,7 @@ manage(Window w, XWindowAttributes *wa) c = ecalloc(1, sizeof(Client)); c->win = w; /* geometry */ + c->sfx = c->sfy = c->sfw = c->sfh = -9999; c->x = c->oldx = wa->x; c->y = c->oldy = wa->y; c->w = c->oldw = wa->width; @@ -1420,7 +1417,6 @@ manage(Window w, XWindowAttributes *wa) settings_restored = restoreclientstate(c); updatetitle(c); - if (XGetTransientForHint(dpy, w, &trans) && (t = wintoclient(trans))) { c->mon = t->mon; c->tags = t->tags; @@ -1428,8 +1424,10 @@ manage(Window w, XWindowAttributes *wa) if (c->x == c->mon->wx && c->y == c->mon->wy) c->iscentered = 1; } else { - if (!settings_restored) + if (!settings_restored || c->mon == NULL) { c->mon = selmon; + settings_restored = 0; + } if (c->x == c->mon->wx && c->y == c->mon->wy) c->iscentered = 1; c->bw = borderpx; @@ -1437,7 +1435,6 @@ manage(Window w, XWindowAttributes *wa) applyrules(c); } - if (c->x + WIDTH(c) > c->mon->wx + c->mon->ww) c->x = c->mon->wx + c->mon->ww - WIDTH(c); if (c->y + HEIGHT(c) > c->mon->wy + c->mon->wh) @@ -1456,8 +1453,12 @@ manage(Window w, XWindowAttributes *wa) updatewmhints(c); if (c->iscentered) { - c->x = c->mon->wx + (c->mon->ww - WIDTH(c)) / 2; - c->y = c->mon->wy + (c->mon->wh - HEIGHT(c)) / 2; + c->sfx = c->x = c->mon->wx + (c->mon->ww - WIDTH(c)) / 2; + c->sfy = c->y = c->mon->wy + (c->mon->wh - HEIGHT(c)) / 2; + } + if (c->sfw == -9999) { + c->sfw = c->w; + c->sfh = c->h; } if (getatomprop(c, netatom[NetWMState], XA_ATOM) == netatom[NetWMFullscreen]) @@ -1486,6 +1487,7 @@ manage(Window w, XWindowAttributes *wa) XMapWindow(dpy, c->win); focus(NULL); + setfloatinghint(c); } void @@ -1504,7 +1506,6 @@ maprequest(XEvent *e) static XWindowAttributes wa; XMapRequestEvent *ev = &e->xmaprequest; - if (!XGetWindowAttributes(dpy, ev->window, &wa) || wa.override_redirect) return; if (!wintoclient(ev->window)) @@ -1514,8 +1515,6 @@ maprequest(XEvent *e) void motionnotify(XEvent *e) { - static Monitor *mon = NULL; - Monitor *m; Bar *bar; XMotionEvent *ev = &e->xmotion; @@ -1524,15 +1523,6 @@ motionnotify(XEvent *e) return; } - - if (ev->window != root) - return; - if ((m = recttomon(ev->x_root, ev->y_root, 1, 1)) != mon && mon) { - unfocus(selmon->sel, 1, NULL); - selmon = m; - focus(NULL); - } - mon = m; } void @@ -1582,6 +1572,7 @@ movemouse(const Arg *arg) ny = selmon->wy + selmon->wh - HEIGHT(c); if (!c->isfloating && selmon->lt[selmon->sellt]->arrange && (abs(nx - c->x) > snap || abs(ny - c->y) > snap)) { + c->sfx = -9999; // disable savefloats when using movemouse togglefloating(NULL); } if (!selmon->lt[selmon->sellt]->arrange || c->isfloating) { @@ -1601,6 +1592,11 @@ movemouse(const Arg *arg) selmon = m; focus(NULL); } + /* save last known float coordinates */ + if (!selmon->lt[selmon->sellt]->arrange || c->isfloating) { + c->sfx = nx; + c->sfy = ny; + } ignoreconfigurerequests = 0; } @@ -1611,6 +1607,29 @@ nexttiled(Client *c) return c; } +int +noborder(Client *c) +{ + int monocle_layout = 0; + + if (&monocle == c->mon->lt[c->mon->sellt]->arrange) + monocle_layout = 1; + + if (!monocle_layout && (nexttiled(c->mon->clients) != c || nexttiled(c->next))) + return 0; + + if (c->isfloating) + return 0; + + if (!c->mon->lt[c->mon->sellt]->arrange) + return 0; + + if (c->fakefullscreen != 1 && c->isfullscreen) + return 0; + + return 1; +} + void pop(Client *c) { @@ -1627,9 +1646,9 @@ propertynotify(XEvent *e) Window trans; XPropertyEvent *ev = &e->xproperty; - if ((ev->window == root) && (ev->atom == XA_WM_NAME)) { - updatestatus(); + if (!fake_signal()) + updatestatus(); } else if (ev->state == PropertyDelete) { return; /* ignore */ } else if ((c = wintoclient(ev->window))) { @@ -1695,14 +1714,9 @@ resizeclient(Client *c, int x, int y, int w, int h) c->oldw = c->w; c->w = wc.width = w; c->oldh = c->h; c->h = wc.height = h; wc.border_width = c->bw; - if (((nexttiled(c->mon->clients) == c && !nexttiled(c->next)) - || &monocle == c->mon->lt[c->mon->sellt]->arrange - ) - && (c->fakefullscreen == 1 || !c->isfullscreen) - && !c->isfloating - && c->mon->lt[c->mon->sellt]->arrange) { - c->w = wc.width += c->bw * 2; - c->h = wc.height += c->bw * 2; + if (noborder(c)) { + wc.width += c->bw * 2; + wc.height += c->bw * 2; wc.border_width = 0; } XConfigureWindow(dpy, c->win, CWX|CWY|CWWidth|CWHeight|CWBorderWidth, &wc); @@ -1753,6 +1767,7 @@ resizemouse(const Arg *arg) { if (!c->isfloating && selmon->lt[selmon->sellt]->arrange && (abs(nw - c->w) > snap || abs(nh - c->h) > snap)) { + c->sfx = -9999; // disable savefloats when using resizemouse togglefloating(NULL); } } @@ -1775,6 +1790,13 @@ resizemouse(const Arg *arg) selmon = m; focus(NULL); } + /* save last known float dimensions */ + if (!selmon->lt[selmon->sellt]->arrange || c->isfloating) { + c->sfx = nx; + c->sfy = ny; + c->sfw = nw; + c->sfh = nh; + } ignoreconfigurerequests = 0; } @@ -1874,6 +1896,8 @@ sendmon(Client *c, Monitor *m) attachstack(c); arrange(NULL); focus(NULL); + if (c->switchtag) + c->switchtag = 0; } void @@ -2049,8 +2073,8 @@ setup(void) drw = drw_create(dpy, screen, root, sw, sh); if (!drw_fontset_create(drw, fonts, LENGTH(fonts))) die("no fonts could be loaded."); - lrpad = drw->fonts->h; - bh = drw->fonts->h + 2; + lrpad = drw->fonts->h + horizpadbar; + bh = drw->fonts->h + vertpadbar; updategeom(); /* init atoms */ utf8string = XInternAtom(dpy, "UTF8_STRING", False); @@ -2062,6 +2086,10 @@ setup(void) clientatom[ClientTags] = XInternAtom(dpy, "_DWM_CLIENT_TAGS", False); netatom[NetActiveWindow] = XInternAtom(dpy, "_NET_ACTIVE_WINDOW", False); netatom[NetSupported] = XInternAtom(dpy, "_NET_SUPPORTED", False); + netatom[NetDesktopViewport] = XInternAtom(dpy, "_NET_DESKTOP_VIEWPORT", False); + netatom[NetNumberOfDesktops] = XInternAtom(dpy, "_NET_NUMBER_OF_DESKTOPS", False); + netatom[NetCurrentDesktop] = XInternAtom(dpy, "_NET_CURRENT_DESKTOP", False); + netatom[NetDesktopNames] = XInternAtom(dpy, "_NET_DESKTOP_NAMES", False); netatom[NetWMName] = XInternAtom(dpy, "_NET_WM_NAME", False); netatom[NetWMState] = XInternAtom(dpy, "_NET_WM_STATE", False); netatom[NetWMCheck] = XInternAtom(dpy, "_NET_SUPPORTING_WM_CHECK", False); @@ -2092,6 +2120,10 @@ setup(void) /* EWMH support per view */ XChangeProperty(dpy, root, netatom[NetSupported], XA_ATOM, 32, PropModeReplace, (unsigned char *) netatom, NetLast); + setnumdesktops(); + setcurrentdesktop(); + setdesktopnames(); + setviewport(); XDeleteProperty(dpy, root, netatom[NetClientList]); /* select events */ wa.cursor = cursor[CurNormal]->cursor; @@ -2101,12 +2133,10 @@ setup(void) XChangeWindowAttributes(dpy, root, CWEventMask|CWCursor, &wa); XSelectInput(dpy, root, wa.event_mask); - grabkeys(); focus(NULL); } - void seturgent(Client *c, int urg) { @@ -2140,6 +2170,12 @@ showhide(Client *c) c->y = c->mon->wy + (c->mon->wh / 2 - HEIGHT(c) / 2); } /* show clients top down */ + if (!c->mon->lt[c->mon->sellt]->arrange && c->sfx != -9999 && !c->isfullscreen) { + XMoveResizeWindow(dpy, c->win, c->sfx, c->sfy, c->sfw, c->sfh); + resize(c, c->sfx, c->sfy, c->sfw, c->sfh, 0); + showhide(c->snext); + return; + } XMoveWindow(dpy, c->win, c->x, c->y); if ((!c->mon->lt[c->mon->sellt]->arrange || c->isfloating) && !c->isfullscreen @@ -2182,7 +2218,6 @@ spawn(const Arg *arg) { struct sigaction sa; - if (fork() == 0) { if (dpy) @@ -2206,6 +2241,8 @@ tag(const Arg *arg) if (selmon->sel && arg->ui & TAGMASK) { selmon->sel->tags = arg->ui & TAGMASK; + if (selmon->sel->switchtag) + selmon->sel->switchtag = 0; arrange(selmon); focus(NULL); } @@ -2216,9 +2253,16 @@ tagmon(const Arg *arg) { Client *c = selmon->sel; Monitor *dest; + int restored; if (!c || !mons->next) return; dest = dirtomon(arg->i); + savewindowfloatposition(c, c->mon); + restored = restorewindowfloatposition(c, dest); + if (restored && (!dest->lt[dest->sellt]->arrange || c->isfloating)) { + XMoveResizeWindow(dpy, c->win, c->sfx, c->sfy, c->sfw, c->sfh); + resize(c, c->sfx, c->sfy, c->sfw, c->sfh, 1); + } sendmon(c, dest); } @@ -2226,7 +2270,7 @@ void togglebar(const Arg *arg) { Bar *bar; - selmon->showbar = !selmon->showbar; + selmon->showbar = (selmon->showbar == 2 ? 1 : !selmon->showbar); updatebarpos(selmon); for (bar = selmon->bar; bar; bar = bar->next) XMoveResizeWindow(dpy, bar->win, bar->bx, bar->by, bar->bw, bar->bh); @@ -2249,10 +2293,21 @@ togglefloating(const Arg *arg) else XSetWindowBorder(dpy, c->win, scheme[SchemeSel][ColBorder].pixel); if (c->isfloating) { + if (c->sfx != -9999) { + /* restore last known float dimensions */ + resize(c, c->sfx, c->sfy, c->sfw, c->sfh, 0); + } else resize(c, c->x, c->y, c->w, c->h, 0); + } else { + /* save last known float dimensions */ + c->sfx = c->x; + c->sfy = c->y; + c->sfw = c->w; + c->sfh = c->h; } arrange(c->mon); + setfloatinghint(c); } void @@ -2268,6 +2323,7 @@ toggletag(const Arg *arg) arrange(selmon); focus(NULL); } + updatecurrentdesktop(); } void @@ -2276,7 +2332,6 @@ toggleview(const Arg *arg) unsigned int newtagset = selmon->tagset[selmon->seltags] ^ (arg->ui & TAGMASK);; int i; - if (newtagset) { selmon->tagset[selmon->seltags] = newtagset; @@ -2299,6 +2354,7 @@ toggleview(const Arg *arg) arrange(selmon); focus(NULL); } + updatecurrentdesktop(); } void @@ -2321,11 +2377,11 @@ void unmanage(Client *c, int destroyed) { Monitor *m; + unsigned int switchtag = c->switchtag; XWindowChanges wc; m = c->mon; - detach(c); detachstack(c); if (!destroyed) { @@ -2341,11 +2397,12 @@ unmanage(Client *c, int destroyed) XUngrabServer(dpy); } - free(c); arrange(m); focus(NULL); updateclientlist(); + if (switchtag && ((switchtag & TAGMASK) != selmon->tagset[selmon->seltags])) + view(&((Arg) { .ui = switchtag })); } void @@ -2401,7 +2458,6 @@ updatebarpos(Monitor *m) int y_pad = 0; int x_pad = 0; - for (bar = m->bar; bar; bar = bar->next) { bar->bx = m->wx + x_pad; bar->bw = m->ww - 2 * x_pad; @@ -2411,7 +2467,6 @@ updatebarpos(Monitor *m) if (!m->showbar || !bar->showbar) bar->by = -bar->bh - y_pad; - if (!m->showbar) return; for (bar = m->bar; bar; bar = bar->next) { @@ -2638,6 +2693,7 @@ view(const Arg *arg) pertagview(arg); arrange(selmon); focus(NULL); + updatecurrentdesktop(); } Client * @@ -2717,8 +2773,6 @@ zoom(const Arg *arg) if (!c) return; - - if (!c->mon->lt[c->mon->sellt]->arrange || !c || c->isfloating) return; diff --git a/.config/suckless/dwm/dwm.desktop b/.config/suckless/dwm/dwm.desktop deleted file mode 100644 index b0c3354..0000000 --- a/.config/suckless/dwm/dwm.desktop +++ /dev/null @@ -1,7 +0,0 @@ -[Desktop Entry] -Encoding=UTF-8 -Name=Dwm -Comment=Dynamic window manager -Exec=dwm -Icon=dwm -Type=XSession diff --git a/.config/suckless/dwm/dwm.png b/.config/suckless/dwm/dwm.png deleted file mode 100644 index b1f9ba7..0000000 Binary files a/.config/suckless/dwm/dwm.png and /dev/null differ diff --git a/.config/suckless/dwm/patch/bar_ewmhtags.c b/.config/suckless/dwm/patch/bar_ewmhtags.c new file mode 100644 index 0000000..46ee5e4 --- /dev/null +++ b/.config/suckless/dwm/patch/bar_ewmhtags.c @@ -0,0 +1,52 @@ +void +setcurrentdesktop(void) +{ + long data[] = { 0 }; + XChangeProperty(dpy, root, netatom[NetCurrentDesktop], XA_CARDINAL, 32, PropModeReplace, (unsigned char *)data, 1); +} + +void +setdesktopnames(void) +{ + int i; + XTextProperty text; + char *tags[NUMTAGS]; + for (i = 0; i < NUMTAGS; i++) + tags[i] = tagicon(selmon, i); + Xutf8TextListToTextProperty(dpy, tags, NUMTAGS, XUTF8StringStyle, &text); + XSetTextProperty(dpy, root, &text, netatom[NetDesktopNames]); +} + +void +setfloatinghint(Client *c) +{ + Atom target = XInternAtom(dpy, "_IS_FLOATING", 0); + unsigned int floating[1] = {c->isfloating}; + XChangeProperty(dpy, c->win, target, XA_CARDINAL, 32, PropModeReplace, (unsigned char *)floating, 1); +} + +void +setnumdesktops(void) +{ + long data[] = { NUMTAGS }; + XChangeProperty(dpy, root, netatom[NetNumberOfDesktops], XA_CARDINAL, 32, PropModeReplace, (unsigned char *)data, 1); +} + +void +setviewport(void) +{ + long data[] = { 0, 0 }; + XChangeProperty(dpy, root, netatom[NetDesktopViewport], XA_CARDINAL, 32, PropModeReplace, (unsigned char *)data, 2); +} + +void +updatecurrentdesktop(void) +{ + long rawdata[] = { selmon->tagset[selmon->seltags] }; + int i = 0; + while (*rawdata >> (i + 1)) { + i++; + } + long data[] = { i }; + XChangeProperty(dpy, root, netatom[NetCurrentDesktop], XA_CARDINAL, 32, PropModeReplace, (unsigned char *)data, 1); +} diff --git a/.config/suckless/dwm/patch/bar_ewmhtags.h b/.config/suckless/dwm/patch/bar_ewmhtags.h new file mode 100644 index 0000000..4d6a74b --- /dev/null +++ b/.config/suckless/dwm/patch/bar_ewmhtags.h @@ -0,0 +1,7 @@ +static void setcurrentdesktop(void); +static void setdesktopnames(void); +static void setfloatinghint(Client *c); +static void setnumdesktops(void); +static void setviewport(void); +static void updatecurrentdesktop(void); + diff --git a/.config/suckless/dwm/patch/bar_holdbar.c b/.config/suckless/dwm/patch/bar_holdbar.c new file mode 100644 index 0000000..ed79877 --- /dev/null +++ b/.config/suckless/dwm/patch/bar_holdbar.c @@ -0,0 +1,36 @@ +void +holdbar(const Arg *arg) +{ + if (selmon->showbar) + return; + Bar *bar; + selmon->showbar = 2; + updatebarpos(selmon); + for (bar = selmon->bar; bar; bar = bar->next) + XMoveResizeWindow(dpy, bar->win, bar->bx, bar->by, bar->bw, bar->bh); + drawbar(selmon); +} + +void +keyrelease(XEvent *e) +{ + Bar *bar; + if (XEventsQueued(dpy, QueuedAfterReading)) { + XEvent ne; + XPeekEvent(dpy, &ne); + + if (ne.type == KeyPress && ne.xkey.time == e->xkey.time && + ne.xkey.keycode == e->xkey.keycode) { + XNextEvent(dpy, &ne); + return; + } + } + if (e->xkey.keycode == XKeysymToKeycode(dpy, HOLDKEY) && selmon->showbar == 2) { + selmon->showbar = 0; + updatebarpos(selmon); + for (bar = selmon->bar; bar; bar = bar->next) + XMoveResizeWindow(dpy, bar->win, bar->bx, bar->by, bar->bw, bar->bh); + arrange(selmon); + } +} + diff --git a/.config/suckless/dwm/patch/bar_holdbar.h b/.config/suckless/dwm/patch/bar_holdbar.h new file mode 100644 index 0000000..bcde089 --- /dev/null +++ b/.config/suckless/dwm/patch/bar_holdbar.h @@ -0,0 +1,3 @@ +static void keyrelease(XEvent *e); +static void holdbar(const Arg *arg); + diff --git a/.config/suckless/dwm/patch/bar_status.c b/.config/suckless/dwm/patch/bar_status.c index 65595e0..19ff219 100644 --- a/.config/suckless/dwm/patch/bar_status.c +++ b/.config/suckless/dwm/patch/bar_status.c @@ -4,14 +4,12 @@ width_status(Bar *bar, BarArg *a) return TEXTWM(stext); } - int draw_status(Bar *bar, BarArg *a) { return drw_text(drw, a->x, a->y, a->w, a->h, lrpad / 2, stext, 0, True); } - int click_status(Bar *bar, Arg *arg, BarArg *a) { diff --git a/.config/suckless/dwm/patch/bar_status2d.c b/.config/suckless/dwm/patch/bar_status2d.c index 85d6043..4586fc2 100644 --- a/.config/suckless/dwm/patch/bar_status2d.c +++ b/.config/suckless/dwm/patch/bar_status2d.c @@ -27,15 +27,12 @@ width_status2d(Bar *bar, BarArg *a) return width ? width + lrpad : 0; } - int draw_status2d(Bar *bar, BarArg *a) { return drawstatusbar(a, rawstext); } - - int drawstatusbar(BarArg *a, char* stext) { diff --git a/.config/suckless/dwm/patch/bar_statuscmd.c b/.config/suckless/dwm/patch/bar_statuscmd.c index 706aa19..c5a639a 100644 --- a/.config/suckless/dwm/patch/bar_statuscmd.c +++ b/.config/suckless/dwm/patch/bar_statuscmd.c @@ -1,11 +1,9 @@ - int click_statuscmd(Bar *bar, Arg *arg, BarArg *a) { return click_statuscmd_text(arg, a->x, rawstext); } - int click_statuscmd_text(Arg *arg, int rel_x, char *text) { diff --git a/.config/suckless/dwm/patch/dwmc b/.config/suckless/dwm/patch/dwmc new file mode 100755 index 0000000..2500ba7 --- /dev/null +++ b/.config/suckless/dwm/patch/dwmc @@ -0,0 +1,136 @@ +#!/usr/bin/env bash + +signal() { + xsetroot -name "fsignal:$*" +} + +case $# in +1) + case $1 in + focusurgent) ;& + mirrorlayout) ;& + mpdcontrol) ;& + nametag) ;& + pushdown) ;& + pushup) ;& + self_restart) ;& + setlayout) ;& + setcfact) ;& + showhideclient) ;& + switchcol) ;& + view) ;& + viewall) ;& + viewtoleft) ;& + viewtoright) ;& + tagtoleft) ;& + tagtoright) ;& + tagandviewtoleft) ;& + tagandviewtoright) ;& + transfer) ;& + transferall) ;& + togglealttag) ;& + togglebar) ;& + toggletopbar) ;& + togglefloating) ;& + togglefullscreen) ;& + fullscreen) ;& + togglefakefullscreen) ;& + togglesticky) ;& + togglehorizontalmax) ;& + toggleverticalmax) ;& + togglemax) ;& + togglegaps) ;& + defaultgaps) ;& + unfloatvisible) ;& + winview) ;& + xrdb) ;& + zoom) ;& + killclient) ;& + quit) + signal $1 + ;; + *) + echo "Unknown command ($1) or missing one argument." + exit 1 + ;; + esac + ;; +2) + case $1 in + cyclelayout) ;& + explace) ;& + moveplace) ;& + mpdchange) ;& + setkeymode) ;& + switchtag) ;& + togglescratch) ;& + view) + signal $1 ui $2 + ;; + viewex) ;& + toggleviewex) ;& + tagallmon) ;& + tagswapmon) ;& + tagex) ;& + toggletagex) ;& + setborderpx) ;& + setgaps) ;& + setlayoutex) ;& + setlayoutaxisex) ;& + swapfocus) ;& + focusstack) ;& + pushstack) ;& + inplacerotate) ;& + rotatestack) ;& + rotatelayoutaxis) ;& + incnmaster) ;& + incnstack) ;& + incrgaps) ;& + incrigaps) ;& + incrogaps) ;& + incrihgaps) ;& + incrivgaps) ;& + incrohgaps) ;& + incrovgaps) ;& + movestack) ;& + shiftview) ;& + shiftviewclients) ;& + focusmon) ;& + tagmon) + signal $1 i $2 + ;; + setcfact) ;& + setmfact) + signal $1 f $2 + ;; + floatpos) + signal $1 v $2 + ;; + *) + echo "Unknown command ($1) or too many arguments" + exit 1 + ;; + esac + ;; +5) + case $1 in + setgaps) + # Expects "setgaps oh ov ih iv" where -1 means to keep existing values + [ $2 = -1 ] && oh=128 || oh=$2 + [ $3 = -1 ] && ov=128 || ov=$3 + [ $4 = -1 ] && ih=128 || ih=$4 + [ $5 = -1 ] && iv=128 || iv=$5 + signal $1 i $(((oh << 24) + (ov << 16) + (ih << 8) + iv)) + ;; + *) + echo "Unknown command ($1) or too many arguments" + exit 1 + ;; + esac + ;; +*) + echo "Unknown command ($1) or too many arguments" + exit 1 + ;; +esac + diff --git a/.config/suckless/dwm/patch/dwmc.c b/.config/suckless/dwm/patch/dwmc.c new file mode 100644 index 0000000..971532f --- /dev/null +++ b/.config/suckless/dwm/patch/dwmc.c @@ -0,0 +1,87 @@ +void +setlayoutex(const Arg *arg) +{ + setlayout(&((Arg) { .v = &layouts[arg->i] })); +} + +void +viewex(const Arg *arg) +{ + view(&((Arg) { .ui = 1 << arg->ui })); +} + +void +viewallex(const Arg *arg) +{ + view(&((Arg){.ui = ~SPTAGMASK})); +} + +void +toggleviewex(const Arg *arg) +{ + toggleview(&((Arg) { .ui = 1 << arg->ui })); +} + +void +tagex(const Arg *arg) +{ + tag(&((Arg) { .ui = 1 << arg->ui })); +} + +void +toggletagex(const Arg *arg) +{ + toggletag(&((Arg) { .ui = 1 << arg->ui })); +} + +void +tagallex(const Arg *arg) +{ + tag(&((Arg){.ui = ~SPTAGMASK})); +} + +int +fake_signal(void) +{ + char fsignal[256]; + char indicator[9] = "fsignal:"; + char str_sig[50]; + char param[16]; + int i, len_str_sig, n, paramn; + size_t len_fsignal, len_indicator = strlen(indicator); + Arg arg; + + // Get root name property + if (gettextprop(root, XA_WM_NAME, fsignal, sizeof(fsignal))) { + len_fsignal = strlen(fsignal); + + // Check if this is indeed a fake signal + if (len_indicator > len_fsignal ? 0 : strncmp(indicator, fsignal, len_indicator) == 0) { + paramn = sscanf(fsignal+len_indicator, "%s%n%s%n", str_sig, &len_str_sig, param, &n); + + if (paramn == 1) arg = (Arg) {0}; + else if (paramn > 2) return 1; + else if (strncmp(param, "i", n - len_str_sig) == 0) + sscanf(fsignal + len_indicator + n, "%i", &(arg.i)); + else if (strncmp(param, "ui", n - len_str_sig) == 0) + sscanf(fsignal + len_indicator + n, "%u", &(arg.ui)); + else if (strncmp(param, "f", n - len_str_sig) == 0) + sscanf(fsignal + len_indicator + n, "%f", &(arg.f)); + else if (strncmp(param, "v", n - len_str_sig) == 0) + arg.v = &(fsignal[len_indicator + n + 1]); + else return 1; + + // Check if a signal was found, and if so handle it + for (i = 0; i < LENGTH(signals); i++) + if (strncmp(str_sig, signals[i].sig, len_str_sig) == 0 && signals[i].func) + signals[i].func(&(arg)); + + // A fake signal was sent + return 1; + } + } + + // No fake signal was sent, so proceed with update + return 0; +} + diff --git a/.config/suckless/dwm/patch/dwmc.h b/.config/suckless/dwm/patch/dwmc.h new file mode 100644 index 0000000..66e23a9 --- /dev/null +++ b/.config/suckless/dwm/patch/dwmc.h @@ -0,0 +1,14 @@ +typedef struct { + const char * sig; + void (*func)(const Arg *); +} Signal; + +static void setlayoutex(const Arg *arg); +static void viewex(const Arg *arg); +static void viewallex(const Arg *arg); +static void toggleviewex(const Arg *arg); +static void tagex(const Arg *arg); +static void toggletagex(const Arg *arg); +static void tagallex(const Arg *arg); +static int fake_signal(void); + diff --git a/.config/suckless/dwm/patch/focusfollowmouse.c b/.config/suckless/dwm/patch/focusfollowmouse.c deleted file mode 100644 index d75a9da..0000000 --- a/.config/suckless/dwm/patch/focusfollowmouse.c +++ /dev/null @@ -1,9 +0,0 @@ -Client * -getpointerclient(void) -{ - Window dummy, win; - int di; - unsigned int dui; - XQueryPointer(dpy, root, &dummy, &win, &di, &di, &di, &di, &dui); - return wintoclient(win); -} diff --git a/.config/suckless/dwm/patch/focusfollowmouse.h b/.config/suckless/dwm/patch/focusfollowmouse.h deleted file mode 100644 index 6b24d5f..0000000 --- a/.config/suckless/dwm/patch/focusfollowmouse.h +++ /dev/null @@ -1 +0,0 @@ -static Client *getpointerclient(void); diff --git a/.config/suckless/dwm/patch/include.c b/.config/suckless/dwm/patch/include.c index 8679033..8cf70b1 100644 --- a/.config/suckless/dwm/patch/include.c +++ b/.config/suckless/dwm/patch/include.c @@ -4,19 +4,22 @@ #include "bar.c" #include "bar_dwmblocks.c" +#include "bar_ewmhtags.c" #include "bar_ltsymbol.c" #include "bar_status.c" #include "bar_status2d.c" #include "bar_statusbutton.c" #include "bar_statuscmd.c" #include "bar_tags.c" +#include "bar_holdbar.c" /* Other patches */ #include "attachx.c" #include "cool_autostart.c" +#include "dwmc.c" #include "fakefullscreenclient.c" #include "focusdir.c" -#include "focusfollowmouse.c" +#include "killunsel.c" #include "pertag.c" #include "restartsig.c" #include "rotatestack.c" diff --git a/.config/suckless/dwm/patch/include.h b/.config/suckless/dwm/patch/include.h index 55d46a8..869ec95 100644 --- a/.config/suckless/dwm/patch/include.h +++ b/.config/suckless/dwm/patch/include.h @@ -4,6 +4,8 @@ #include "bar.h" #include "bar_dwmblocks.h" +#include "bar_ewmhtags.h" +#include "bar_holdbar.h" #include "bar_ltsymbol.h" #include "bar_status.h" #include "bar_status2d.h" @@ -14,9 +16,10 @@ /* Other patches */ #include "attachx.h" #include "cool_autostart.h" +#include "dwmc.h" #include "fakefullscreenclient.h" #include "focusdir.h" -#include "focusfollowmouse.h" +#include "killunsel.h" #include "pertag.h" #include "restartsig.h" #include "rotatestack.h" diff --git a/.config/suckless/dwm/patch/killunsel.c b/.config/suckless/dwm/patch/killunsel.c new file mode 100644 index 0000000..d457b53 --- /dev/null +++ b/.config/suckless/dwm/patch/killunsel.c @@ -0,0 +1,24 @@ +void +killunsel(const Arg *arg) +{ + Client *i = NULL; + + if (!selmon->sel) + return; + + for (i = selmon->clients; i; i = i->next) { + if (ISVISIBLE(i) && i != selmon->sel) { + if (!sendevent(i, wmatom[WMDelete])) + { + XGrabServer(dpy); + XSetErrorHandler(xerrordummy); + XSetCloseDownMode(dpy, DestroyAll); + XKillClient(dpy, i->win); + XSync(dpy, False); + XSetErrorHandler(xerror); + XUngrabServer(dpy); + } + } + } +} + diff --git a/.config/suckless/dwm/patch/killunsel.h b/.config/suckless/dwm/patch/killunsel.h new file mode 100644 index 0000000..4fc154f --- /dev/null +++ b/.config/suckless/dwm/patch/killunsel.h @@ -0,0 +1,2 @@ +static void killunsel(const Arg *arg); + diff --git a/.config/suckless/dwm/patch/layout_tile.c b/.config/suckless/dwm/patch/layout_tile.c index 629b321..76b0078 100644 --- a/.config/suckless/dwm/patch/layout_tile.c +++ b/.config/suckless/dwm/patch/layout_tile.c @@ -8,7 +8,6 @@ tile(Monitor *m) int mrest, srest; Client *c; - for (n = 0, c = nexttiled(m->clients); c; c = nexttiled(c->next), n++); if (n == 0) diff --git a/.config/suckless/dwm/patch/pertag.c b/.config/suckless/dwm/patch/pertag.c index 024799e..16e7222 100644 --- a/.config/suckless/dwm/patch/pertag.c +++ b/.config/suckless/dwm/patch/pertag.c @@ -24,6 +24,5 @@ pertagview(const Arg *arg) selmon->lt[selmon->sellt] = selmon->pertag->ltidxs[selmon->pertag->curtag][selmon->sellt]; selmon->lt[selmon->sellt^1] = selmon->pertag->ltidxs[selmon->pertag->curtag][selmon->sellt^1]; - } diff --git a/.config/suckless/dwm/patch/seamless_restart.c b/.config/suckless/dwm/patch/seamless_restart.c index febdc32..289121e 100644 --- a/.config/suckless/dwm/patch/seamless_restart.c +++ b/.config/suckless/dwm/patch/seamless_restart.c @@ -25,14 +25,16 @@ persistclientstate(Client *c) { setclienttags(c); setclientfields(c); + savewindowfloatposition(c, c->mon); } int restoreclientstate(Client *c) { - return getclienttags(c) - | getclientfields(c) - ; + int restored = getclientfields(c); + getclienttags(c); + restorewindowfloatposition(c, c->mon ? c->mon : selmon); + return restored; } void setmonitorfields(Monitor *m) @@ -237,3 +239,76 @@ getclienttags(Client *c) return 1; } +void +savewindowfloatposition(Client *c, Monitor *m) +{ + char atom[22] = {0}; + if (c->sfx == -9999) + return; + + sprintf(atom, "_DWM_FLOATPOS_%u", m->num); + uint32_t pos[] = { (MAX(c->sfx - m->mx, 0) & 0xffff) | ((MAX(c->sfy - m->my, 0) & 0xffff) << 16) }; + XChangeProperty(dpy, c->win, XInternAtom(dpy, atom, False), XA_CARDINAL, 32, PropModeReplace, (unsigned char *)pos, 1); + + sprintf(atom, "_DWM_FLOATSIZE_%u", m->num); + uint32_t size[] = { (c->sfw & 0xffff) | ((c->sfh & 0xffff) << 16) }; + XChangeProperty(dpy, c->win, XInternAtom(dpy, atom, False), XA_CARDINAL, 32, PropModeReplace, (unsigned char *)size, 1); + + XSync(dpy, False); +} + +int +restorewindowfloatposition(Client *c, Monitor *m) +{ + char atom[22] = {0}; + Atom key, value; + int x, y, w, h; + + if (m == NULL) + return 0; + + sprintf(atom, "_DWM_FLOATPOS_%u", m->num); + + key = XInternAtom(dpy, atom, False); + if (!key) + return 0; + + value = getatomprop(c, key, AnyPropertyType); + if (!value) + return 0; + + x = value & 0xffff; + y = value >> 16; + + sprintf(atom, "_DWM_FLOATSIZE_%u", m->num); + + key = XInternAtom(dpy, atom, False); + if (!key) + return 0; + + value = getatomprop(c, key, AnyPropertyType); + if (!value) + return 0; + + w = value & 0xffff; + h = value >> 16; + + if (w <= 0 || h <= 0) { + fprintf(stderr, "restorewindowfloatposition: bad float values x = %d, y = %d, w = %d, h = %d for client = %s\n", x, y, w, h, c->name); + return 0; + } + + c->sfx = m->mx + x; + c->sfy = m->my + y; + c->sfw = w; + c->sfh = h; + + if (c->isfloating) { + c->x = c->sfx; + c->y = c->sfy; + c->w = c->sfw; + c->h = c->sfh; + } + + return 1; +} diff --git a/.config/suckless/dwm/patch/seamless_restart.h b/.config/suckless/dwm/patch/seamless_restart.h index 13c5d6d..4d95b6a 100644 --- a/.config/suckless/dwm/patch/seamless_restart.h +++ b/.config/suckless/dwm/patch/seamless_restart.h @@ -13,3 +13,5 @@ static int getclientfields(Client *c); static void setclienttags(Client *c); static int getclienttags(Client *c); static int getlayoutindex(const Layout *layout); +static void savewindowfloatposition(Client *c, Monitor *m); +static int restorewindowfloatposition(Client *c, Monitor *m); diff --git a/.config/suckless/dwm/patch/xrdb.h b/.config/suckless/dwm/patch/xrdb.h index 3787bec..304f2e2 100644 --- a/.config/suckless/dwm/patch/xrdb.h +++ b/.config/suckless/dwm/patch/xrdb.h @@ -19,4 +19,3 @@ static void loadxrdb(void); static void xrdb(const Arg *arg); - diff --git a/.config/suckless/dwm/transient.c b/.config/suckless/dwm/transient.c deleted file mode 100644 index 158460f..0000000 --- a/.config/suckless/dwm/transient.c +++ /dev/null @@ -1,43 +0,0 @@ -/* cc transient.c -o transient -lX11 */ - -#include -#include -#include -#include - -int main(void) { - Display *d; - Window r, f, t = None; - XSizeHints h; - XEvent e; - - d = XOpenDisplay(NULL); - if (!d) - exit(1); - r = DefaultRootWindow(d); - - f = XCreateSimpleWindow(d, r, 100, 100, 400, 400, 0, 0, 0); - h.min_width = h.max_width = h.min_height = h.max_height = 400; - h.flags = PMinSize | PMaxSize; - XSetWMNormalHints(d, f, &h); - XStoreName(d, f, "floating"); - XMapWindow(d, f); - - XSelectInput(d, f, ExposureMask); - while (1) { - XNextEvent(d, &e); - - if (t == None) { - sleep(5); - t = XCreateSimpleWindow(d, r, 50, 50, 100, 100, 0, 0, 0); - XSetTransientForHint(d, t, f); - XStoreName(d, t, "transient"); - XMapWindow(d, t); - XSelectInput(d, t, ExposureMask); - } - } - - XCloseDisplay(d); - exit(0); -} -