Compare commits
2 Commits
e33e206e31
...
d2b40dc8e3
Author | SHA1 | Date |
---|---|---|
Alex Kotov | d2b40dc8e3 | |
Alex Kotov | 3d277c10fa |
1
Makefile
1
Makefile
|
@ -42,6 +42,7 @@ DWM_SRC = \
|
||||||
src/dwm/bar.c \
|
src/dwm/bar.c \
|
||||||
src/dwm/handlers.c \
|
src/dwm/handlers.c \
|
||||||
src/dwm/layouts.c \
|
src/dwm/layouts.c \
|
||||||
|
src/dwm/wmcheckwin.c \
|
||||||
src/dwm/xerror.c
|
src/dwm/xerror.c
|
||||||
|
|
||||||
TEST_SRC = \
|
TEST_SRC = \
|
||||||
|
|
729
src/dwm.c
729
src/dwm.c
|
@ -150,39 +150,27 @@ static void arrange(Monitor *m);
|
||||||
static void arrangemon(Monitor *m);
|
static void arrangemon(Monitor *m);
|
||||||
static void attach(Client *c);
|
static void attach(Client *c);
|
||||||
static void attachstack(Client *c);
|
static void attachstack(Client *c);
|
||||||
static void configborder(const Arg *arg);
|
|
||||||
static void configgap(const Arg *arg);
|
|
||||||
static void configure(Client *c);
|
static void configure(Client *c);
|
||||||
static void detach(Client *c);
|
static void detach(Client *c);
|
||||||
static void detachstack(Client *c);
|
static void detachstack(Client *c);
|
||||||
static Monitor *dirtomon(int dir);
|
static Monitor *dirtomon(int dir);
|
||||||
static void dorestart(const Arg *arg);
|
|
||||||
static void focus(Client *c);
|
static void focus(Client *c);
|
||||||
static void focusmon(const Arg *arg);
|
|
||||||
static void focusstack(const Arg *arg);
|
|
||||||
static Atom getatomprop(Client *c, Atom prop);
|
static Atom getatomprop(Client *c, Atom prop);
|
||||||
static int getrootptr(int *x, int *y);
|
static int getrootptr(int *x, int *y);
|
||||||
static long getstate(Window w);
|
static long getstate(Window w);
|
||||||
static int gettextprop(Window w, Atom atom, char *text, unsigned int size);
|
static int gettextprop(Window w, Atom atom, char *text, unsigned int size);
|
||||||
static void grabbuttons(Client *c, int focused);
|
static void grabbuttons(Client *c, int focused);
|
||||||
static void grabkeys();
|
static void grabkeys();
|
||||||
static void incnmaster(const Arg *arg);
|
|
||||||
static int isuniquegeom(XineramaScreenInfo *unique, size_t n, XineramaScreenInfo *info);
|
static int isuniquegeom(XineramaScreenInfo *unique, size_t n, XineramaScreenInfo *info);
|
||||||
static void killclient(const Arg *arg);
|
|
||||||
static void manage(Window w, XWindowAttributes *wa);
|
static void manage(Window w, XWindowAttributes *wa);
|
||||||
static void managepolybar(Window w, XWindowAttributes *wa);
|
static void managepolybar(Window w, XWindowAttributes *wa);
|
||||||
static Monitor *monitor_create();
|
static Monitor *monitor_create();
|
||||||
static void monitor_destroy(Monitor *mon);
|
static void monitor_destroy(Monitor *mon);
|
||||||
static void movemouse(const Arg *arg);
|
|
||||||
static void movestack(const Arg *arg);
|
|
||||||
static Client *nexttiled(Client *c);
|
static Client *nexttiled(Client *c);
|
||||||
static void pop(Client *);
|
static void pop(Client *);
|
||||||
static void quit(const Arg *arg);
|
|
||||||
static Monitor *recttomon(int x, int y, int w, int h);
|
static Monitor *recttomon(int x, int y, int w, int h);
|
||||||
static void resetnmaster(const Arg *arg);
|
|
||||||
static void resize(Client *c, struct WinGeom win_geom, int interact);
|
static void resize(Client *c, struct WinGeom win_geom, int interact);
|
||||||
static void resizeclient(Client *c, struct WinGeom win_geom);
|
static void resizeclient(Client *c, struct WinGeom win_geom);
|
||||||
static void resizemouse(const Arg *arg);
|
|
||||||
static void restack(Monitor *m);
|
static void restack(Monitor *m);
|
||||||
static void run();
|
static void run();
|
||||||
static void scan();
|
static void scan();
|
||||||
|
@ -193,14 +181,8 @@ static void sendmon(Client *c, Monitor *m);
|
||||||
static void setclientstate(Client *c, long state);
|
static void setclientstate(Client *c, long state);
|
||||||
static void setfocus(Client *c);
|
static void setfocus(Client *c);
|
||||||
static void setfullscreen(Client *c, int fullscreen);
|
static void setfullscreen(Client *c, int fullscreen);
|
||||||
static void setlayout(const Arg *arg);
|
|
||||||
static void setmfact(const Arg *arg);
|
|
||||||
static void seturgent(Client *c, bool is_urgent);
|
static void seturgent(Client *c, bool is_urgent);
|
||||||
static void showhide(Client *c);
|
static void showhide(Client *c);
|
||||||
static void spawn(const Arg *arg);
|
|
||||||
static void spawn_callback();
|
|
||||||
static void tagmon(const Arg *arg);
|
|
||||||
static void togglefloating(const Arg *arg);
|
|
||||||
static void unfocus(Client *c, int setfocus);
|
static void unfocus(Client *c, int setfocus);
|
||||||
static void unmanage(Client *c, int destroyed);
|
static void unmanage(Client *c, int destroyed);
|
||||||
static void updateclientlist();
|
static void updateclientlist();
|
||||||
|
@ -212,13 +194,14 @@ static void updatewindowtype(Client *c);
|
||||||
static void updatewmhints(Client *c);
|
static void updatewmhints(Client *c);
|
||||||
static Client *wintoclient(Window w);
|
static Client *wintoclient(Window w);
|
||||||
static Monitor *wintomon(Window w);
|
static Monitor *wintomon(Window w);
|
||||||
static void wmcheckwin_create();
|
|
||||||
static void wmcheckwin_destroy();
|
extern const Layout layouts[];
|
||||||
static void zoom(const Arg *arg);
|
|
||||||
|
|
||||||
#include "dwm/bar.h"
|
#include "dwm/bar.h"
|
||||||
#include "dwm/handlers.h"
|
#include "dwm/handlers.h"
|
||||||
|
#include "dwm/interaction.h"
|
||||||
#include "dwm/layouts.h"
|
#include "dwm/layouts.h"
|
||||||
|
#include "dwm/wmcheckwin.h"
|
||||||
#include "dwm/xerror.h"
|
#include "dwm/xerror.h"
|
||||||
|
|
||||||
/*************
|
/*************
|
||||||
|
@ -236,7 +219,6 @@ static Cur *cursor[CurLast];
|
||||||
static Clr **scheme;
|
static Clr **scheme;
|
||||||
static Drw *drw;
|
static Drw *drw;
|
||||||
static Monitor *mons, *selmon;
|
static Monitor *mons, *selmon;
|
||||||
static Window wmcheckwin;
|
|
||||||
|
|
||||||
static void (*handler[LASTEvent])(XEvent*) = {
|
static void (*handler[LASTEvent])(XEvent*) = {
|
||||||
[ButtonPress] = on_button_press,
|
[ButtonPress] = on_button_press,
|
||||||
|
@ -267,7 +249,7 @@ static const char *colors[][3] = {
|
||||||
[SchemeSel] = { col_gray4, col_cyan, "#d9b01c" },
|
[SchemeSel] = { col_gray4, col_cyan, "#d9b01c" },
|
||||||
};
|
};
|
||||||
|
|
||||||
static const Layout layouts[] = {
|
const Layout layouts[] = {
|
||||||
/* symbol function, arrange function */
|
/* symbol function, arrange function */
|
||||||
{ layouts_symbol_monocle, monocle }, /* first entry is default */
|
{ layouts_symbol_monocle, monocle }, /* first entry is default */
|
||||||
{ layouts_symbol_floating, NULL }, /* no layout function means floating behavior */
|
{ layouts_symbol_floating, NULL }, /* no layout function means floating behavior */
|
||||||
|
@ -276,66 +258,15 @@ static const Layout layouts[] = {
|
||||||
{ layouts_symbol_centeredmaster, centeredmaster },
|
{ layouts_symbol_centeredmaster, centeredmaster },
|
||||||
};
|
};
|
||||||
|
|
||||||
#define MODKEY Mod4Mask
|
|
||||||
|
|
||||||
static Key keys[] = {
|
|
||||||
// WM
|
|
||||||
{ MODKEY|ControlMask|ShiftMask, XK_q, quit, {0} },
|
|
||||||
{ MODKEY|ControlMask|ShiftMask, XK_r, dorestart, {0} },
|
|
||||||
// Monitor
|
|
||||||
{ MODKEY, XK_bracketleft, focusmon, {.i = -1 } },
|
|
||||||
{ MODKEY, XK_bracketright, focusmon, {.i = +1 } },
|
|
||||||
{ MODKEY|ShiftMask, XK_bracketleft, tagmon, {.i = -1 } },
|
|
||||||
{ MODKEY|ShiftMask, XK_bracketright, tagmon, {.i = +1 } },
|
|
||||||
// Layout
|
|
||||||
{ MODKEY, XK_m, setlayout, {.v = &layouts[0]} }, // Monocle
|
|
||||||
{ MODKEY, XK_f, setlayout, {.v = &layouts[1]} }, // Floating
|
|
||||||
{ MODKEY, XK_t, setlayout, {.v = &layouts[2]} }, // Tile
|
|
||||||
{ MODKEY|ShiftMask, XK_t, setlayout, {.v = &layouts[3]} }, // Horizontile
|
|
||||||
{ MODKEY, XK_u, setlayout, {.v = &layouts[4]} }, // Centeredmaster
|
|
||||||
{ MODKEY, XK_space, setlayout, {0} },
|
|
||||||
{ MODKEY, XK_i, incnmaster, {.i = +1 } },
|
|
||||||
{ MODKEY|ShiftMask, XK_i, resetnmaster, {.i = 1 } },
|
|
||||||
{ MODKEY, XK_d, incnmaster, {.i = -1 } },
|
|
||||||
{ MODKEY|ShiftMask, XK_d, resetnmaster, {.i = 0 } },
|
|
||||||
// Stack
|
|
||||||
{ MODKEY, XK_j, focusstack, {.i = +1 } },
|
|
||||||
{ MODKEY, XK_k, focusstack, {.i = -1 } },
|
|
||||||
{ MODKEY|ShiftMask, XK_j, movestack, {.i = +1 } },
|
|
||||||
{ MODKEY|ShiftMask, XK_k, movestack, {.i = -1 } },
|
|
||||||
{ MODKEY, XK_Return, zoom, {0} },
|
|
||||||
// Window
|
|
||||||
{ MODKEY|ShiftMask, XK_x, killclient, {0} },
|
|
||||||
{ MODKEY|ShiftMask, XK_space, togglefloating, {0} },
|
|
||||||
// Appearance
|
|
||||||
{ MODKEY, XK_h, setmfact, {.f = -0.05} },
|
|
||||||
{ MODKEY, XK_l, setmfact, {.f = +0.05} },
|
|
||||||
{ MODKEY|Mod1Mask, XK_b, configborder, {.i = -1 } },
|
|
||||||
{ MODKEY|Mod1Mask|ShiftMask, XK_b, configborder, {.i = +1 } },
|
|
||||||
{ MODKEY|Mod1Mask, XK_g, configgap, {.i = -1 } },
|
|
||||||
{ MODKEY|Mod1Mask|ShiftMask, XK_g, configgap, {.i = +1 } },
|
|
||||||
// Starting applications
|
|
||||||
{ MODKEY, XK_z, spawn, {.v = "lock" } },
|
|
||||||
{ MODKEY, XK_slash, spawn, {.v = "menu" } },
|
|
||||||
{ MODKEY|ShiftMask, XK_slash, spawn, {.v = "term" } },
|
|
||||||
{ MODKEY|ShiftMask, XK_f, spawn, {.v = "firefox" } },
|
|
||||||
};
|
|
||||||
|
|
||||||
// click can be ClkClientWin, or ClkRootWin
|
|
||||||
static Button buttons[] = {
|
|
||||||
/* click event mask button function argument */
|
|
||||||
{ ClkClientWin, MODKEY, Button1, movemouse, {0} },
|
|
||||||
{ ClkClientWin, MODKEY, Button2, togglefloating, {0} },
|
|
||||||
{ ClkClientWin, MODKEY, Button3, resizemouse, {0} },
|
|
||||||
};
|
|
||||||
|
|
||||||
/************************************
|
/************************************
|
||||||
* Private function implementations *
|
* Private function implementations *
|
||||||
************************************/
|
************************************/
|
||||||
|
|
||||||
#include "dwm/bar.c"
|
#include "dwm/bar.c"
|
||||||
#include "dwm/handlers.c"
|
#include "dwm/handlers.c"
|
||||||
|
#include "dwm/interaction.c"
|
||||||
#include "dwm/layouts.c"
|
#include "dwm/layouts.c"
|
||||||
|
#include "dwm/wmcheckwin.c"
|
||||||
#include "dwm/xerror.c"
|
#include "dwm/xerror.c"
|
||||||
|
|
||||||
/***********************************
|
/***********************************
|
||||||
|
@ -648,24 +579,6 @@ void attachstack(Client *c)
|
||||||
c->mon->stack = c;
|
c->mon->stack = c;
|
||||||
}
|
}
|
||||||
|
|
||||||
void configborder(const Arg *const arg)
|
|
||||||
{
|
|
||||||
if (arg == NULL) return;
|
|
||||||
const int old_border_width = settings_get_border_width();
|
|
||||||
const int new_border_width = old_border_width + (arg->i >= 0 ? +1 : -1);
|
|
||||||
settings_set_border_width(new_border_width);
|
|
||||||
arrange(selmon);
|
|
||||||
}
|
|
||||||
|
|
||||||
void configgap(const Arg *const arg)
|
|
||||||
{
|
|
||||||
if (arg == NULL) return;
|
|
||||||
const int old_gap_size = settings_get_gap_size();
|
|
||||||
const int new_gap_size = old_gap_size + (arg->i >= 0 ? +2 : -2);
|
|
||||||
settings_set_gap_size(new_gap_size);
|
|
||||||
arrange(selmon);
|
|
||||||
}
|
|
||||||
|
|
||||||
void configure(Client *c)
|
void configure(Client *c)
|
||||||
{
|
{
|
||||||
XConfigureEvent ce = {
|
XConfigureEvent ce = {
|
||||||
|
@ -728,11 +641,6 @@ Monitor *dirtomon(int dir)
|
||||||
return m;
|
return m;
|
||||||
}
|
}
|
||||||
|
|
||||||
void dorestart(__attribute__((unused)) const Arg *const arg)
|
|
||||||
{
|
|
||||||
restart();
|
|
||||||
}
|
|
||||||
|
|
||||||
void focus(Client *c)
|
void focus(Client *c)
|
||||||
{
|
{
|
||||||
if (!c || !ISVISIBLE(c))
|
if (!c || !ISVISIBLE(c))
|
||||||
|
@ -769,67 +677,6 @@ void focus(Client *c)
|
||||||
selmon->sel = c;
|
selmon->sel = c;
|
||||||
}
|
}
|
||||||
|
|
||||||
void focusmon(const Arg *arg)
|
|
||||||
{
|
|
||||||
if (!mons->next) return;
|
|
||||||
|
|
||||||
Monitor *m;
|
|
||||||
if ((m = dirtomon(arg->i)) == selmon) return;
|
|
||||||
|
|
||||||
unfocus(selmon->sel, 0);
|
|
||||||
selmon = m;
|
|
||||||
focus(NULL);
|
|
||||||
}
|
|
||||||
|
|
||||||
void focusstack(const Arg *arg)
|
|
||||||
{
|
|
||||||
if (!selmon->sel) return;
|
|
||||||
|
|
||||||
Client *c = NULL;
|
|
||||||
|
|
||||||
if (arg->i > 0) {
|
|
||||||
for (c = selmon->sel->next; c && !ISVISIBLE(c); c = c->next);
|
|
||||||
|
|
||||||
if (!c) {
|
|
||||||
for (c = selmon->clients; c && !ISVISIBLE(c); c = c->next);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
Client *i = selmon->clients;
|
|
||||||
|
|
||||||
for (; i != selmon->sel; i = i->next) {
|
|
||||||
if (ISVISIBLE(i)) {
|
|
||||||
c = i;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!c) {
|
|
||||||
for (; i; i = i->next) {
|
|
||||||
if (ISVISIBLE(i)) {
|
|
||||||
c = i;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (c) {
|
|
||||||
focus(c);
|
|
||||||
restack(selmon);
|
|
||||||
|
|
||||||
{
|
|
||||||
unsigned int n = 0;
|
|
||||||
for (Client *cc = nexttiled(selmon->clients); cc; cc = nexttiled(cc->next), ++n);
|
|
||||||
|
|
||||||
// TODO: Maybe it's an unnecessary optimization
|
|
||||||
// and we don't need the condition.
|
|
||||||
if (n > 1) {
|
|
||||||
// We have to rearrange because borders and gaps may have
|
|
||||||
// changed in monocle layout.
|
|
||||||
arrange(selmon);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Atom getatomprop(Client *c, Atom prop)
|
Atom getatomprop(Client *c, Atom prop)
|
||||||
{
|
{
|
||||||
Atom atom = None;
|
Atom atom = None;
|
||||||
|
@ -1027,19 +874,6 @@ void grabkeys()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void incnmaster(const Arg *arg)
|
|
||||||
{
|
|
||||||
const int max_clients_in_master = settings_get_max_clients_in_master();
|
|
||||||
const int new_clients_in_master = MAX(0, selmon->nmaster + arg->i);
|
|
||||||
|
|
||||||
selmon->nmaster =
|
|
||||||
max_clients_in_master == 0
|
|
||||||
? new_clients_in_master
|
|
||||||
: MIN(new_clients_in_master, max_clients_in_master);
|
|
||||||
|
|
||||||
arrange(selmon);
|
|
||||||
}
|
|
||||||
|
|
||||||
#ifdef ENABLE_XINERAMA
|
#ifdef ENABLE_XINERAMA
|
||||||
int isuniquegeom(XineramaScreenInfo *unique, size_t n, XineramaScreenInfo *info)
|
int isuniquegeom(XineramaScreenInfo *unique, size_t n, XineramaScreenInfo *info)
|
||||||
{
|
{
|
||||||
|
@ -1051,21 +885,6 @@ int isuniquegeom(XineramaScreenInfo *unique, size_t n, XineramaScreenInfo *info)
|
||||||
}
|
}
|
||||||
#endif /* ENABLE_XINERAMA */
|
#endif /* ENABLE_XINERAMA */
|
||||||
|
|
||||||
void killclient(__attribute__((unused)) const Arg *arg)
|
|
||||||
{
|
|
||||||
if (!selmon->sel)
|
|
||||||
return;
|
|
||||||
if (!sendevent(selmon->sel, xbase->atoms->wmatom[WMDelete])) {
|
|
||||||
XGrabServer(xbase->x_display);
|
|
||||||
XSetErrorHandler(xerrordummy);
|
|
||||||
XSetCloseDownMode(xbase->x_display, DestroyAll);
|
|
||||||
XKillClient(xbase->x_display, selmon->sel->x_window);
|
|
||||||
XSync(xbase->x_display, False);
|
|
||||||
XSetErrorHandler(xerror);
|
|
||||||
XUngrabServer(xbase->x_display);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void manage(Window w, XWindowAttributes *wa)
|
void manage(Window w, XWindowAttributes *wa)
|
||||||
{
|
{
|
||||||
Client *const c = ecalloc(1, sizeof(Client));
|
Client *const c = ecalloc(1, sizeof(Client));
|
||||||
|
@ -1261,219 +1080,6 @@ void monitor_destroy(Monitor *mon)
|
||||||
free(mon);
|
free(mon);
|
||||||
}
|
}
|
||||||
|
|
||||||
void movemouse(__attribute__((unused)) const Arg *arg)
|
|
||||||
{
|
|
||||||
Client *const c = selmon->sel;
|
|
||||||
if (c == NULL) return;
|
|
||||||
|
|
||||||
restack(selmon);
|
|
||||||
|
|
||||||
if (
|
|
||||||
XGrabPointer(
|
|
||||||
xbase->x_display,
|
|
||||||
xbase->x_root,
|
|
||||||
False,
|
|
||||||
MOUSEMASK,
|
|
||||||
GrabModeAsync,
|
|
||||||
GrabModeAsync,
|
|
||||||
None,
|
|
||||||
cursor[CurMove]->cursor,
|
|
||||||
CurrentTime
|
|
||||||
) != GrabSuccess
|
|
||||||
) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
int x, y;
|
|
||||||
if (!getrootptr(&x, &y)) return;
|
|
||||||
|
|
||||||
const unsigned int snap_distance = settings_get_snap_distance();
|
|
||||||
const int ocx = c->state.geom.basic.position.x;
|
|
||||||
const int ocy = c->state.geom.basic.position.y;
|
|
||||||
|
|
||||||
Time lasttime = 0;
|
|
||||||
|
|
||||||
XEvent ev;
|
|
||||||
|
|
||||||
do {
|
|
||||||
XMaskEvent(
|
|
||||||
xbase->x_display,
|
|
||||||
MOUSEMASK | ExposureMask | SubstructureRedirectMask,
|
|
||||||
&ev
|
|
||||||
);
|
|
||||||
|
|
||||||
switch (ev.type) {
|
|
||||||
case ConfigureRequest:
|
|
||||||
case Expose:
|
|
||||||
case MapRequest:
|
|
||||||
handler[ev.type](&ev);
|
|
||||||
break;
|
|
||||||
case MotionNotify:
|
|
||||||
if ((ev.xmotion.time - lasttime) <= (1000 / 60)) continue;
|
|
||||||
|
|
||||||
lasttime = ev.xmotion.time;
|
|
||||||
|
|
||||||
int nx = ocx + (ev.xmotion.x - x);
|
|
||||||
int ny = ocy + (ev.xmotion.y - y);
|
|
||||||
|
|
||||||
if (
|
|
||||||
abs(selmon->window_area_geom.position.x - nx)
|
|
||||||
<
|
|
||||||
snap_distance
|
|
||||||
) {
|
|
||||||
nx = selmon->window_area_geom.position.x;
|
|
||||||
} else if (
|
|
||||||
abs(
|
|
||||||
(
|
|
||||||
selmon->window_area_geom.position.x
|
|
||||||
+
|
|
||||||
selmon->window_area_geom.sizes.w
|
|
||||||
)
|
|
||||||
-
|
|
||||||
(nx + win_geom_total_width(&c->state.geom))
|
|
||||||
)
|
|
||||||
<
|
|
||||||
snap_distance
|
|
||||||
) {
|
|
||||||
nx =
|
|
||||||
selmon->window_area_geom.position.x
|
|
||||||
+
|
|
||||||
selmon->window_area_geom.sizes.w
|
|
||||||
-
|
|
||||||
win_geom_total_width(&c->state.geom);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (
|
|
||||||
abs(selmon->window_area_geom.position.y - ny)
|
|
||||||
<
|
|
||||||
snap_distance
|
|
||||||
) {
|
|
||||||
ny = selmon->window_area_geom.position.y;
|
|
||||||
} else if (
|
|
||||||
abs(
|
|
||||||
(
|
|
||||||
selmon->window_area_geom.position.y
|
|
||||||
+
|
|
||||||
selmon->window_area_geom.sizes.h
|
|
||||||
) - (ny + win_geom_total_height(&c->state.geom))
|
|
||||||
)
|
|
||||||
<
|
|
||||||
snap_distance
|
|
||||||
) {
|
|
||||||
ny =
|
|
||||||
selmon->window_area_geom.position.y
|
|
||||||
+
|
|
||||||
selmon->window_area_geom.sizes.h
|
|
||||||
-
|
|
||||||
win_geom_total_height(&c->state.geom);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (
|
|
||||||
!c->state.is_floating
|
|
||||||
&&
|
|
||||||
(
|
|
||||||
abs(nx - c->state.geom.basic.position.x) > snap_distance
|
|
||||||
||
|
|
||||||
abs(ny - c->state.geom.basic.position.y) > snap_distance)
|
|
||||||
) {
|
|
||||||
togglefloating(NULL);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!selmon->lt[selmon->sellt]->arrange || c->state.is_floating) {
|
|
||||||
struct WinGeom win_geom = c->state.geom;
|
|
||||||
position_init_from_args(&win_geom.basic.position, nx, ny);
|
|
||||||
resize(c, win_geom, 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
} while (ev.type != ButtonRelease);
|
|
||||||
|
|
||||||
XUngrabPointer(xbase->x_display, CurrentTime);
|
|
||||||
|
|
||||||
Monitor *const m = recttomon(
|
|
||||||
c->state.geom.basic.position.x,
|
|
||||||
c->state.geom.basic.position.y,
|
|
||||||
c->state.geom.basic.sizes.w,
|
|
||||||
c->state.geom.basic.sizes.h
|
|
||||||
);
|
|
||||||
|
|
||||||
if (m != selmon) {
|
|
||||||
sendmon(c, m);
|
|
||||||
selmon = m;
|
|
||||||
focus(NULL);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void movestack(const Arg *arg)
|
|
||||||
{
|
|
||||||
Client *c = NULL, *p = NULL, *pc = NULL, *i = NULL;
|
|
||||||
|
|
||||||
if (arg->i > 0) {
|
|
||||||
/* find the client after selmon->sel */
|
|
||||||
for (
|
|
||||||
c = selmon->sel->next;
|
|
||||||
c && (!ISVISIBLE(c) || c->state.is_floating);
|
|
||||||
c = c->next
|
|
||||||
);
|
|
||||||
|
|
||||||
if(!c) {
|
|
||||||
for(
|
|
||||||
c = selmon->clients;
|
|
||||||
c && (!ISVISIBLE(c) || c->state.is_floating);
|
|
||||||
c = c->next
|
|
||||||
);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
/* find the client before selmon->sel */
|
|
||||||
for (i = selmon->clients; i != selmon->sel; i = i->next) {
|
|
||||||
if (ISVISIBLE(i) && !i->state.is_floating) {
|
|
||||||
c = i;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!c) {
|
|
||||||
for (; i; i = i->next) {
|
|
||||||
if (ISVISIBLE(i) && !i->state.is_floating) {
|
|
||||||
c = i;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* find the client before selmon->sel and c */
|
|
||||||
for (i = selmon->clients; i && (!p || !pc); i = i->next) {
|
|
||||||
if (i->next == selmon->sel) {
|
|
||||||
p = i;
|
|
||||||
}
|
|
||||||
if (i->next == c) {
|
|
||||||
pc = i;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* swap c and selmon->sel selmon->clients in the selmon->clients list */
|
|
||||||
if (c && c != selmon->sel) {
|
|
||||||
Client *temp = selmon->sel->next == c ? selmon->sel : selmon->sel->next;
|
|
||||||
selmon->sel->next = c->next==selmon->sel?c:c->next;
|
|
||||||
c->next = temp;
|
|
||||||
|
|
||||||
if (p && p != c) {
|
|
||||||
p->next = c;
|
|
||||||
}
|
|
||||||
if (pc && pc != selmon->sel) {
|
|
||||||
pc->next = selmon->sel;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (selmon->sel == selmon->clients) {
|
|
||||||
selmon->clients = c;
|
|
||||||
} else if (c == selmon->clients) {
|
|
||||||
selmon->clients = selmon->sel;
|
|
||||||
}
|
|
||||||
|
|
||||||
arrange(selmon);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Client *nexttiled(Client *c)
|
Client *nexttiled(Client *c)
|
||||||
{
|
{
|
||||||
for (; c && (c->state.is_floating || !ISVISIBLE(c)); c = c->next);
|
for (; c && (c->state.is_floating || !ISVISIBLE(c)); c = c->next);
|
||||||
|
@ -1488,11 +1094,6 @@ void pop(Client *c)
|
||||||
arrange(c->mon);
|
arrange(c->mon);
|
||||||
}
|
}
|
||||||
|
|
||||||
void quit(__attribute__((unused)) const Arg *arg)
|
|
||||||
{
|
|
||||||
running = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
Monitor *recttomon(int x, int y, int w, int h)
|
Monitor *recttomon(int x, int y, int w, int h)
|
||||||
{
|
{
|
||||||
Monitor *m, *r = selmon;
|
Monitor *m, *r = selmon;
|
||||||
|
@ -1506,19 +1107,6 @@ Monitor *recttomon(int x, int y, int w, int h)
|
||||||
return r;
|
return r;
|
||||||
}
|
}
|
||||||
|
|
||||||
void resetnmaster(const Arg *arg)
|
|
||||||
{
|
|
||||||
const int max_clients_in_master = settings_get_max_clients_in_master();
|
|
||||||
const int new_clients_in_master = arg->i == 0 ? 0 : settings_get_default_clients_in_master();
|
|
||||||
|
|
||||||
selmon->nmaster =
|
|
||||||
max_clients_in_master == 0
|
|
||||||
? new_clients_in_master
|
|
||||||
: MIN(new_clients_in_master, max_clients_in_master);
|
|
||||||
|
|
||||||
arrange(selmon);
|
|
||||||
}
|
|
||||||
|
|
||||||
void resize(Client *c, struct WinGeom win_geom, int interact)
|
void resize(Client *c, struct WinGeom win_geom, int interact)
|
||||||
{
|
{
|
||||||
if (applysizehints(c, &win_geom, interact)) {
|
if (applysizehints(c, &win_geom, interact)) {
|
||||||
|
@ -1544,164 +1132,6 @@ void resizeclient(Client *c, const struct WinGeom win_geom)
|
||||||
XSync(xbase->x_display, False);
|
XSync(xbase->x_display, False);
|
||||||
}
|
}
|
||||||
|
|
||||||
void resizemouse(__attribute__((unused)) const Arg *arg)
|
|
||||||
{
|
|
||||||
Client *const c = selmon->sel;
|
|
||||||
if (c == NULL) return;
|
|
||||||
|
|
||||||
restack(selmon);
|
|
||||||
|
|
||||||
if (
|
|
||||||
XGrabPointer(
|
|
||||||
xbase->x_display,
|
|
||||||
xbase->x_root,
|
|
||||||
False,
|
|
||||||
MOUSEMASK,
|
|
||||||
GrabModeAsync,
|
|
||||||
GrabModeAsync,
|
|
||||||
None,
|
|
||||||
cursor[CurResize]->cursor,
|
|
||||||
CurrentTime
|
|
||||||
) != GrabSuccess
|
|
||||||
) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
XWarpPointer(
|
|
||||||
xbase->x_display,
|
|
||||||
None,
|
|
||||||
c->x_window,
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
c->state.geom.basic.sizes.w + c->state.geom.border_width - 1,
|
|
||||||
c->state.geom.basic.sizes.h + c->state.geom.border_width - 1
|
|
||||||
);
|
|
||||||
|
|
||||||
const unsigned int snap_distance = settings_get_snap_distance();
|
|
||||||
const int ocx = c->state.geom.basic.position.x;
|
|
||||||
const int ocy = c->state.geom.basic.position.y;
|
|
||||||
|
|
||||||
Time lasttime = 0;
|
|
||||||
|
|
||||||
XEvent ev;
|
|
||||||
|
|
||||||
do {
|
|
||||||
XMaskEvent(
|
|
||||||
xbase->x_display,
|
|
||||||
MOUSEMASK | ExposureMask | SubstructureRedirectMask,
|
|
||||||
&ev
|
|
||||||
);
|
|
||||||
|
|
||||||
switch (ev.type) {
|
|
||||||
case ConfigureRequest:
|
|
||||||
case Expose:
|
|
||||||
case MapRequest:
|
|
||||||
handler[ev.type](&ev);
|
|
||||||
break;
|
|
||||||
case MotionNotify:
|
|
||||||
if ((ev.xmotion.time - lasttime) <= (1000 / 60)) continue;
|
|
||||||
|
|
||||||
lasttime = ev.xmotion.time;
|
|
||||||
|
|
||||||
const int nw = MAX(
|
|
||||||
ev.xmotion.x - ocx - 2 * c->state.geom.border_width + 1,
|
|
||||||
1
|
|
||||||
);
|
|
||||||
const int nh = MAX(
|
|
||||||
ev.xmotion.y - ocy - 2 * c->state.geom.border_width + 1,
|
|
||||||
1
|
|
||||||
);
|
|
||||||
|
|
||||||
if (
|
|
||||||
(
|
|
||||||
c->mon->window_area_geom.position.x + nw
|
|
||||||
>=
|
|
||||||
selmon->window_area_geom.position.x
|
|
||||||
)
|
|
||||||
&&
|
|
||||||
(
|
|
||||||
c->mon->window_area_geom.position.x + nw
|
|
||||||
<=
|
|
||||||
(
|
|
||||||
selmon->window_area_geom.position.x
|
|
||||||
+
|
|
||||||
selmon->window_area_geom.sizes.w
|
|
||||||
)
|
|
||||||
)
|
|
||||||
&&
|
|
||||||
(
|
|
||||||
c->mon->window_area_geom.position.y + nh
|
|
||||||
>=
|
|
||||||
selmon->window_area_geom.position.y
|
|
||||||
)
|
|
||||||
&&
|
|
||||||
(
|
|
||||||
c->mon->window_area_geom.position.y + nh
|
|
||||||
<=
|
|
||||||
(
|
|
||||||
selmon->window_area_geom.position.y
|
|
||||||
+
|
|
||||||
selmon->window_area_geom.sizes.h
|
|
||||||
)
|
|
||||||
)
|
|
||||||
) {
|
|
||||||
if (
|
|
||||||
!c->state.is_floating
|
|
||||||
&&
|
|
||||||
(
|
|
||||||
selmon->lt[selmon->sellt]->arrange == NULL
|
|
||||||
||
|
|
||||||
abs(nw - c->state.geom.basic.sizes.w) > snap_distance
|
|
||||||
||
|
|
||||||
abs(nh - c->state.geom.basic.sizes.h) > snap_distance
|
|
||||||
)
|
|
||||||
) {
|
|
||||||
togglefloating(NULL);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!selmon->lt[selmon->sellt]->arrange || c->state.is_floating) {
|
|
||||||
struct WinGeom win_geom = c->state.geom;
|
|
||||||
sizes_init_from_args(&win_geom.basic.sizes, nw, nh);
|
|
||||||
resize(c, win_geom, 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
} while (ev.type != ButtonRelease);
|
|
||||||
|
|
||||||
XWarpPointer(
|
|
||||||
xbase->x_display,
|
|
||||||
None,
|
|
||||||
c->x_window,
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
c->state.geom.basic.sizes.w + c->state.geom.border_width - 1,
|
|
||||||
c->state.geom.basic.sizes.h + c->state.geom.border_width - 1
|
|
||||||
);
|
|
||||||
|
|
||||||
XUngrabPointer(xbase->x_display, CurrentTime);
|
|
||||||
|
|
||||||
while (XCheckMaskEvent(xbase->x_display, EnterWindowMask, &ev));
|
|
||||||
|
|
||||||
Monitor *const m = recttomon(
|
|
||||||
c->state.geom.basic.position.x,
|
|
||||||
c->state.geom.basic.position.y,
|
|
||||||
c->state.geom.basic.sizes.w,
|
|
||||||
c->state.geom.basic.sizes.h
|
|
||||||
);
|
|
||||||
|
|
||||||
if (m != selmon) {
|
|
||||||
sendmon(c, m);
|
|
||||||
selmon = m;
|
|
||||||
focus(NULL);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void restack(Monitor *m)
|
void restack(Monitor *m)
|
||||||
{
|
{
|
||||||
Client *c;
|
Client *c;
|
||||||
|
@ -1924,38 +1354,6 @@ void setfullscreen(Client *c, int fullscreen)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void setlayout(const Arg *arg)
|
|
||||||
{
|
|
||||||
if (!arg || !arg->v || arg->v != selmon->lt[selmon->sellt]) {
|
|
||||||
selmon->sellt ^= 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (arg && arg->v) {
|
|
||||||
const Layout *const new_layout = arg->v;
|
|
||||||
selmon->lt[selmon->sellt] = new_layout;
|
|
||||||
}
|
|
||||||
|
|
||||||
unsigned int visible_clients = 0;
|
|
||||||
for (const Client *client = selmon->clients; client; client = client->next) {
|
|
||||||
if (ISVISIBLE(client)) ++visible_clients;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (selmon->sel) {
|
|
||||||
arrange(selmon);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void setmfact(const Arg *arg)
|
|
||||||
{
|
|
||||||
if (!arg) return;
|
|
||||||
|
|
||||||
unit_inc_master_area_factor(selmon->unit, arg->f);
|
|
||||||
|
|
||||||
for (Monitor *m = mons; m; m = m->next) {
|
|
||||||
arrange(m);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void seturgent(Client *c, bool is_urgent)
|
void seturgent(Client *c, bool is_urgent)
|
||||||
{
|
{
|
||||||
XWMHints *wmh;
|
XWMHints *wmh;
|
||||||
|
@ -1998,54 +1396,6 @@ void showhide(Client *c)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void spawn(const Arg *arg)
|
|
||||||
{
|
|
||||||
const char *const command_name = arg->v;
|
|
||||||
|
|
||||||
spawn_command(command_name, spawn_callback, selmon->num);
|
|
||||||
}
|
|
||||||
|
|
||||||
void spawn_callback()
|
|
||||||
{
|
|
||||||
if (xbase->x_display) {
|
|
||||||
close(ConnectionNumber(xbase->x_display));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void tagmon(const Arg *arg)
|
|
||||||
{
|
|
||||||
if (!selmon->sel || !mons->next)
|
|
||||||
return;
|
|
||||||
sendmon(selmon->sel, dirtomon(arg->i));
|
|
||||||
}
|
|
||||||
|
|
||||||
void togglefloating(__attribute__((unused)) const Arg *arg)
|
|
||||||
{
|
|
||||||
if (!selmon->sel) return;
|
|
||||||
|
|
||||||
selmon->sel->state.is_floating =
|
|
||||||
!selmon->sel->state.is_floating || selmon->sel->state.is_fixed;
|
|
||||||
|
|
||||||
const int border_width = settings_get_border_width();
|
|
||||||
|
|
||||||
if (selmon->sel->state.is_floating) {
|
|
||||||
struct WinGeom win_geom = selmon->sel->state.geom;
|
|
||||||
|
|
||||||
win_geom.basic.sizes = sizes_create_from_args(
|
|
||||||
selmon->sel->state.geom.basic.sizes.w -
|
|
||||||
2 * (border_width - selmon->sel->state.geom.border_width),
|
|
||||||
selmon->sel->state.geom.basic.sizes.h -
|
|
||||||
2 * (border_width - selmon->sel->state.geom.border_width)
|
|
||||||
);
|
|
||||||
|
|
||||||
win_geom.border_width = border_width;
|
|
||||||
|
|
||||||
resize(selmon->sel, win_geom, 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
arrange(selmon);
|
|
||||||
}
|
|
||||||
|
|
||||||
void unfocus(Client *c, int setfocus)
|
void unfocus(Client *c, int setfocus)
|
||||||
{
|
{
|
||||||
if (!c)
|
if (!c)
|
||||||
|
@ -2332,68 +1682,3 @@ Monitor *wintomon(Window w)
|
||||||
|
|
||||||
return selmon;
|
return selmon;
|
||||||
}
|
}
|
||||||
|
|
||||||
void wmcheckwin_create()
|
|
||||||
{
|
|
||||||
wmcheckwin = XCreateSimpleWindow(
|
|
||||||
xbase->x_display,
|
|
||||||
xbase->x_root,
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
1,
|
|
||||||
1,
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
0
|
|
||||||
);
|
|
||||||
|
|
||||||
XChangeProperty(
|
|
||||||
xbase->x_display,
|
|
||||||
wmcheckwin,
|
|
||||||
xbase->atoms->netatom[NetWMCheck],
|
|
||||||
XA_WINDOW,
|
|
||||||
32,
|
|
||||||
PropModeReplace,
|
|
||||||
(unsigned char*)&wmcheckwin,
|
|
||||||
1
|
|
||||||
);
|
|
||||||
XChangeProperty(
|
|
||||||
xbase->x_display,
|
|
||||||
wmcheckwin,
|
|
||||||
xbase->atoms->netatom[NetWMName],
|
|
||||||
xbase->atoms->utf8string,
|
|
||||||
8,
|
|
||||||
PropModeReplace,
|
|
||||||
(unsigned char*)
|
|
||||||
xbase->program_title,
|
|
||||||
strlen(xbase->program_title)
|
|
||||||
);
|
|
||||||
XChangeProperty(
|
|
||||||
xbase->x_display,
|
|
||||||
xbase->x_root,
|
|
||||||
xbase->atoms->netatom[NetWMCheck],
|
|
||||||
XA_WINDOW,
|
|
||||||
32,
|
|
||||||
PropModeReplace,
|
|
||||||
(unsigned char*)&wmcheckwin,
|
|
||||||
1
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
void wmcheckwin_destroy()
|
|
||||||
{
|
|
||||||
XDestroyWindow(xbase->x_display, wmcheckwin);
|
|
||||||
}
|
|
||||||
|
|
||||||
void zoom(__attribute__((unused)) const Arg *arg)
|
|
||||||
{
|
|
||||||
Client *c = selmon->sel;
|
|
||||||
|
|
||||||
if (!selmon->lt[selmon->sellt]->arrange
|
|
||||||
|| (selmon->sel && selmon->sel->state.is_floating))
|
|
||||||
return;
|
|
||||||
if (c == nexttiled(selmon->clients))
|
|
||||||
if (!c || !(c = nexttiled(c->next)))
|
|
||||||
return;
|
|
||||||
pop(c);
|
|
||||||
}
|
|
||||||
|
|
|
@ -0,0 +1,593 @@
|
||||||
|
void configborder(const Arg *const arg)
|
||||||
|
{
|
||||||
|
if (arg == NULL) return;
|
||||||
|
const int old_border_width = settings_get_border_width();
|
||||||
|
const int new_border_width = old_border_width + (arg->i >= 0 ? +1 : -1);
|
||||||
|
settings_set_border_width(new_border_width);
|
||||||
|
arrange(selmon);
|
||||||
|
}
|
||||||
|
|
||||||
|
void configgap(const Arg *const arg)
|
||||||
|
{
|
||||||
|
if (arg == NULL) return;
|
||||||
|
const int old_gap_size = settings_get_gap_size();
|
||||||
|
const int new_gap_size = old_gap_size + (arg->i >= 0 ? +2 : -2);
|
||||||
|
settings_set_gap_size(new_gap_size);
|
||||||
|
arrange(selmon);
|
||||||
|
}
|
||||||
|
|
||||||
|
void dorestart(__attribute__((unused)) const Arg *const arg)
|
||||||
|
{
|
||||||
|
restart();
|
||||||
|
}
|
||||||
|
|
||||||
|
void focusmon(const Arg *arg)
|
||||||
|
{
|
||||||
|
if (!mons->next) return;
|
||||||
|
|
||||||
|
Monitor *m;
|
||||||
|
if ((m = dirtomon(arg->i)) == selmon) return;
|
||||||
|
|
||||||
|
unfocus(selmon->sel, 0);
|
||||||
|
selmon = m;
|
||||||
|
focus(NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
void focusstack(const Arg *arg)
|
||||||
|
{
|
||||||
|
if (!selmon->sel) return;
|
||||||
|
|
||||||
|
Client *c = NULL;
|
||||||
|
|
||||||
|
if (arg->i > 0) {
|
||||||
|
for (c = selmon->sel->next; c && !ISVISIBLE(c); c = c->next);
|
||||||
|
|
||||||
|
if (!c) {
|
||||||
|
for (c = selmon->clients; c && !ISVISIBLE(c); c = c->next);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
Client *i = selmon->clients;
|
||||||
|
|
||||||
|
for (; i != selmon->sel; i = i->next) {
|
||||||
|
if (ISVISIBLE(i)) {
|
||||||
|
c = i;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!c) {
|
||||||
|
for (; i; i = i->next) {
|
||||||
|
if (ISVISIBLE(i)) {
|
||||||
|
c = i;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (c) {
|
||||||
|
focus(c);
|
||||||
|
restack(selmon);
|
||||||
|
|
||||||
|
{
|
||||||
|
unsigned int n = 0;
|
||||||
|
for (Client *cc = nexttiled(selmon->clients); cc; cc = nexttiled(cc->next), ++n);
|
||||||
|
|
||||||
|
// TODO: Maybe it's an unnecessary optimization
|
||||||
|
// and we don't need the condition.
|
||||||
|
if (n > 1) {
|
||||||
|
// We have to rearrange because borders and gaps may have
|
||||||
|
// changed in monocle layout.
|
||||||
|
arrange(selmon);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void incnmaster(const Arg *arg)
|
||||||
|
{
|
||||||
|
const int max_clients_in_master = settings_get_max_clients_in_master();
|
||||||
|
const int new_clients_in_master = MAX(0, selmon->nmaster + arg->i);
|
||||||
|
|
||||||
|
selmon->nmaster =
|
||||||
|
max_clients_in_master == 0
|
||||||
|
? new_clients_in_master
|
||||||
|
: MIN(new_clients_in_master, max_clients_in_master);
|
||||||
|
|
||||||
|
arrange(selmon);
|
||||||
|
}
|
||||||
|
|
||||||
|
void killclient(__attribute__((unused)) const Arg *arg)
|
||||||
|
{
|
||||||
|
if (!selmon->sel)
|
||||||
|
return;
|
||||||
|
if (!sendevent(selmon->sel, xbase->atoms->wmatom[WMDelete])) {
|
||||||
|
XGrabServer(xbase->x_display);
|
||||||
|
XSetErrorHandler(xerrordummy);
|
||||||
|
XSetCloseDownMode(xbase->x_display, DestroyAll);
|
||||||
|
XKillClient(xbase->x_display, selmon->sel->x_window);
|
||||||
|
XSync(xbase->x_display, False);
|
||||||
|
XSetErrorHandler(xerror);
|
||||||
|
XUngrabServer(xbase->x_display);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void movemouse(__attribute__((unused)) const Arg *arg)
|
||||||
|
{
|
||||||
|
Client *const c = selmon->sel;
|
||||||
|
if (c == NULL) return;
|
||||||
|
|
||||||
|
restack(selmon);
|
||||||
|
|
||||||
|
if (
|
||||||
|
XGrabPointer(
|
||||||
|
xbase->x_display,
|
||||||
|
xbase->x_root,
|
||||||
|
False,
|
||||||
|
MOUSEMASK,
|
||||||
|
GrabModeAsync,
|
||||||
|
GrabModeAsync,
|
||||||
|
None,
|
||||||
|
cursor[CurMove]->cursor,
|
||||||
|
CurrentTime
|
||||||
|
) != GrabSuccess
|
||||||
|
) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
int x, y;
|
||||||
|
if (!getrootptr(&x, &y)) return;
|
||||||
|
|
||||||
|
const unsigned int snap_distance = settings_get_snap_distance();
|
||||||
|
const int ocx = c->state.geom.basic.position.x;
|
||||||
|
const int ocy = c->state.geom.basic.position.y;
|
||||||
|
|
||||||
|
Time lasttime = 0;
|
||||||
|
|
||||||
|
XEvent ev;
|
||||||
|
|
||||||
|
do {
|
||||||
|
XMaskEvent(
|
||||||
|
xbase->x_display,
|
||||||
|
MOUSEMASK | ExposureMask | SubstructureRedirectMask,
|
||||||
|
&ev
|
||||||
|
);
|
||||||
|
|
||||||
|
switch (ev.type) {
|
||||||
|
case ConfigureRequest:
|
||||||
|
case Expose:
|
||||||
|
case MapRequest:
|
||||||
|
handler[ev.type](&ev);
|
||||||
|
break;
|
||||||
|
case MotionNotify:
|
||||||
|
if ((ev.xmotion.time - lasttime) <= (1000 / 60)) continue;
|
||||||
|
|
||||||
|
lasttime = ev.xmotion.time;
|
||||||
|
|
||||||
|
int nx = ocx + (ev.xmotion.x - x);
|
||||||
|
int ny = ocy + (ev.xmotion.y - y);
|
||||||
|
|
||||||
|
if (
|
||||||
|
abs(selmon->window_area_geom.position.x - nx)
|
||||||
|
<
|
||||||
|
snap_distance
|
||||||
|
) {
|
||||||
|
nx = selmon->window_area_geom.position.x;
|
||||||
|
} else if (
|
||||||
|
abs(
|
||||||
|
(
|
||||||
|
selmon->window_area_geom.position.x
|
||||||
|
+
|
||||||
|
selmon->window_area_geom.sizes.w
|
||||||
|
)
|
||||||
|
-
|
||||||
|
(nx + win_geom_total_width(&c->state.geom))
|
||||||
|
)
|
||||||
|
<
|
||||||
|
snap_distance
|
||||||
|
) {
|
||||||
|
nx =
|
||||||
|
selmon->window_area_geom.position.x
|
||||||
|
+
|
||||||
|
selmon->window_area_geom.sizes.w
|
||||||
|
-
|
||||||
|
win_geom_total_width(&c->state.geom);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (
|
||||||
|
abs(selmon->window_area_geom.position.y - ny)
|
||||||
|
<
|
||||||
|
snap_distance
|
||||||
|
) {
|
||||||
|
ny = selmon->window_area_geom.position.y;
|
||||||
|
} else if (
|
||||||
|
abs(
|
||||||
|
(
|
||||||
|
selmon->window_area_geom.position.y
|
||||||
|
+
|
||||||
|
selmon->window_area_geom.sizes.h
|
||||||
|
) - (ny + win_geom_total_height(&c->state.geom))
|
||||||
|
)
|
||||||
|
<
|
||||||
|
snap_distance
|
||||||
|
) {
|
||||||
|
ny =
|
||||||
|
selmon->window_area_geom.position.y
|
||||||
|
+
|
||||||
|
selmon->window_area_geom.sizes.h
|
||||||
|
-
|
||||||
|
win_geom_total_height(&c->state.geom);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (
|
||||||
|
!c->state.is_floating
|
||||||
|
&&
|
||||||
|
(
|
||||||
|
abs(nx - c->state.geom.basic.position.x) > snap_distance
|
||||||
|
||
|
||||||
|
abs(ny - c->state.geom.basic.position.y) > snap_distance)
|
||||||
|
) {
|
||||||
|
togglefloating(NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!selmon->lt[selmon->sellt]->arrange || c->state.is_floating) {
|
||||||
|
struct WinGeom win_geom = c->state.geom;
|
||||||
|
position_init_from_args(&win_geom.basic.position, nx, ny);
|
||||||
|
resize(c, win_geom, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
} while (ev.type != ButtonRelease);
|
||||||
|
|
||||||
|
XUngrabPointer(xbase->x_display, CurrentTime);
|
||||||
|
|
||||||
|
Monitor *const m = recttomon(
|
||||||
|
c->state.geom.basic.position.x,
|
||||||
|
c->state.geom.basic.position.y,
|
||||||
|
c->state.geom.basic.sizes.w,
|
||||||
|
c->state.geom.basic.sizes.h
|
||||||
|
);
|
||||||
|
|
||||||
|
if (m != selmon) {
|
||||||
|
sendmon(c, m);
|
||||||
|
selmon = m;
|
||||||
|
focus(NULL);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void movestack(const Arg *arg)
|
||||||
|
{
|
||||||
|
Client *c = NULL, *p = NULL, *pc = NULL, *i = NULL;
|
||||||
|
|
||||||
|
if (arg->i > 0) {
|
||||||
|
/* find the client after selmon->sel */
|
||||||
|
for (
|
||||||
|
c = selmon->sel->next;
|
||||||
|
c && (!ISVISIBLE(c) || c->state.is_floating);
|
||||||
|
c = c->next
|
||||||
|
);
|
||||||
|
|
||||||
|
if(!c) {
|
||||||
|
for(
|
||||||
|
c = selmon->clients;
|
||||||
|
c && (!ISVISIBLE(c) || c->state.is_floating);
|
||||||
|
c = c->next
|
||||||
|
);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
/* find the client before selmon->sel */
|
||||||
|
for (i = selmon->clients; i != selmon->sel; i = i->next) {
|
||||||
|
if (ISVISIBLE(i) && !i->state.is_floating) {
|
||||||
|
c = i;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!c) {
|
||||||
|
for (; i; i = i->next) {
|
||||||
|
if (ISVISIBLE(i) && !i->state.is_floating) {
|
||||||
|
c = i;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* find the client before selmon->sel and c */
|
||||||
|
for (i = selmon->clients; i && (!p || !pc); i = i->next) {
|
||||||
|
if (i->next == selmon->sel) {
|
||||||
|
p = i;
|
||||||
|
}
|
||||||
|
if (i->next == c) {
|
||||||
|
pc = i;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* swap c and selmon->sel selmon->clients in the selmon->clients list */
|
||||||
|
if (c && c != selmon->sel) {
|
||||||
|
Client *temp = selmon->sel->next == c ? selmon->sel : selmon->sel->next;
|
||||||
|
selmon->sel->next = c->next==selmon->sel?c:c->next;
|
||||||
|
c->next = temp;
|
||||||
|
|
||||||
|
if (p && p != c) {
|
||||||
|
p->next = c;
|
||||||
|
}
|
||||||
|
if (pc && pc != selmon->sel) {
|
||||||
|
pc->next = selmon->sel;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (selmon->sel == selmon->clients) {
|
||||||
|
selmon->clients = c;
|
||||||
|
} else if (c == selmon->clients) {
|
||||||
|
selmon->clients = selmon->sel;
|
||||||
|
}
|
||||||
|
|
||||||
|
arrange(selmon);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void quit(__attribute__((unused)) const Arg *arg)
|
||||||
|
{
|
||||||
|
running = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void resetnmaster(const Arg *arg)
|
||||||
|
{
|
||||||
|
const int max_clients_in_master = settings_get_max_clients_in_master();
|
||||||
|
const int new_clients_in_master = arg->i == 0 ? 0 : settings_get_default_clients_in_master();
|
||||||
|
|
||||||
|
selmon->nmaster =
|
||||||
|
max_clients_in_master == 0
|
||||||
|
? new_clients_in_master
|
||||||
|
: MIN(new_clients_in_master, max_clients_in_master);
|
||||||
|
|
||||||
|
arrange(selmon);
|
||||||
|
}
|
||||||
|
|
||||||
|
void resizemouse(__attribute__((unused)) const Arg *arg)
|
||||||
|
{
|
||||||
|
Client *const c = selmon->sel;
|
||||||
|
if (c == NULL) return;
|
||||||
|
|
||||||
|
restack(selmon);
|
||||||
|
|
||||||
|
if (
|
||||||
|
XGrabPointer(
|
||||||
|
xbase->x_display,
|
||||||
|
xbase->x_root,
|
||||||
|
False,
|
||||||
|
MOUSEMASK,
|
||||||
|
GrabModeAsync,
|
||||||
|
GrabModeAsync,
|
||||||
|
None,
|
||||||
|
cursor[CurResize]->cursor,
|
||||||
|
CurrentTime
|
||||||
|
) != GrabSuccess
|
||||||
|
) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
XWarpPointer(
|
||||||
|
xbase->x_display,
|
||||||
|
None,
|
||||||
|
c->x_window,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
c->state.geom.basic.sizes.w + c->state.geom.border_width - 1,
|
||||||
|
c->state.geom.basic.sizes.h + c->state.geom.border_width - 1
|
||||||
|
);
|
||||||
|
|
||||||
|
const unsigned int snap_distance = settings_get_snap_distance();
|
||||||
|
const int ocx = c->state.geom.basic.position.x;
|
||||||
|
const int ocy = c->state.geom.basic.position.y;
|
||||||
|
|
||||||
|
Time lasttime = 0;
|
||||||
|
|
||||||
|
XEvent ev;
|
||||||
|
|
||||||
|
do {
|
||||||
|
XMaskEvent(
|
||||||
|
xbase->x_display,
|
||||||
|
MOUSEMASK | ExposureMask | SubstructureRedirectMask,
|
||||||
|
&ev
|
||||||
|
);
|
||||||
|
|
||||||
|
switch (ev.type) {
|
||||||
|
case ConfigureRequest:
|
||||||
|
case Expose:
|
||||||
|
case MapRequest:
|
||||||
|
handler[ev.type](&ev);
|
||||||
|
break;
|
||||||
|
case MotionNotify:
|
||||||
|
if ((ev.xmotion.time - lasttime) <= (1000 / 60)) continue;
|
||||||
|
|
||||||
|
lasttime = ev.xmotion.time;
|
||||||
|
|
||||||
|
const int nw = MAX(
|
||||||
|
ev.xmotion.x - ocx - 2 * c->state.geom.border_width + 1,
|
||||||
|
1
|
||||||
|
);
|
||||||
|
const int nh = MAX(
|
||||||
|
ev.xmotion.y - ocy - 2 * c->state.geom.border_width + 1,
|
||||||
|
1
|
||||||
|
);
|
||||||
|
|
||||||
|
if (
|
||||||
|
(
|
||||||
|
c->mon->window_area_geom.position.x + nw
|
||||||
|
>=
|
||||||
|
selmon->window_area_geom.position.x
|
||||||
|
)
|
||||||
|
&&
|
||||||
|
(
|
||||||
|
c->mon->window_area_geom.position.x + nw
|
||||||
|
<=
|
||||||
|
(
|
||||||
|
selmon->window_area_geom.position.x
|
||||||
|
+
|
||||||
|
selmon->window_area_geom.sizes.w
|
||||||
|
)
|
||||||
|
)
|
||||||
|
&&
|
||||||
|
(
|
||||||
|
c->mon->window_area_geom.position.y + nh
|
||||||
|
>=
|
||||||
|
selmon->window_area_geom.position.y
|
||||||
|
)
|
||||||
|
&&
|
||||||
|
(
|
||||||
|
c->mon->window_area_geom.position.y + nh
|
||||||
|
<=
|
||||||
|
(
|
||||||
|
selmon->window_area_geom.position.y
|
||||||
|
+
|
||||||
|
selmon->window_area_geom.sizes.h
|
||||||
|
)
|
||||||
|
)
|
||||||
|
) {
|
||||||
|
if (
|
||||||
|
!c->state.is_floating
|
||||||
|
&&
|
||||||
|
(
|
||||||
|
selmon->lt[selmon->sellt]->arrange == NULL
|
||||||
|
||
|
||||||
|
abs(nw - c->state.geom.basic.sizes.w) > snap_distance
|
||||||
|
||
|
||||||
|
abs(nh - c->state.geom.basic.sizes.h) > snap_distance
|
||||||
|
)
|
||||||
|
) {
|
||||||
|
togglefloating(NULL);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!selmon->lt[selmon->sellt]->arrange || c->state.is_floating) {
|
||||||
|
struct WinGeom win_geom = c->state.geom;
|
||||||
|
sizes_init_from_args(&win_geom.basic.sizes, nw, nh);
|
||||||
|
resize(c, win_geom, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
} while (ev.type != ButtonRelease);
|
||||||
|
|
||||||
|
XWarpPointer(
|
||||||
|
xbase->x_display,
|
||||||
|
None,
|
||||||
|
c->x_window,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
c->state.geom.basic.sizes.w + c->state.geom.border_width - 1,
|
||||||
|
c->state.geom.basic.sizes.h + c->state.geom.border_width - 1
|
||||||
|
);
|
||||||
|
|
||||||
|
XUngrabPointer(xbase->x_display, CurrentTime);
|
||||||
|
|
||||||
|
while (XCheckMaskEvent(xbase->x_display, EnterWindowMask, &ev));
|
||||||
|
|
||||||
|
Monitor *const m = recttomon(
|
||||||
|
c->state.geom.basic.position.x,
|
||||||
|
c->state.geom.basic.position.y,
|
||||||
|
c->state.geom.basic.sizes.w,
|
||||||
|
c->state.geom.basic.sizes.h
|
||||||
|
);
|
||||||
|
|
||||||
|
if (m != selmon) {
|
||||||
|
sendmon(c, m);
|
||||||
|
selmon = m;
|
||||||
|
focus(NULL);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void setlayout(const Arg *arg)
|
||||||
|
{
|
||||||
|
if (!arg || !arg->v || arg->v != selmon->lt[selmon->sellt]) {
|
||||||
|
selmon->sellt ^= 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (arg && arg->v) {
|
||||||
|
const Layout *const new_layout = arg->v;
|
||||||
|
selmon->lt[selmon->sellt] = new_layout;
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned int visible_clients = 0;
|
||||||
|
for (const Client *client = selmon->clients; client; client = client->next) {
|
||||||
|
if (ISVISIBLE(client)) ++visible_clients;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (selmon->sel) {
|
||||||
|
arrange(selmon);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void setmfact(const Arg *arg)
|
||||||
|
{
|
||||||
|
if (!arg) return;
|
||||||
|
|
||||||
|
unit_inc_master_area_factor(selmon->unit, arg->f);
|
||||||
|
|
||||||
|
for (Monitor *m = mons; m; m = m->next) {
|
||||||
|
arrange(m);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void spawn(const Arg *arg)
|
||||||
|
{
|
||||||
|
const char *const command_name = arg->v;
|
||||||
|
|
||||||
|
spawn_command(command_name, spawn_callback, selmon->num);
|
||||||
|
}
|
||||||
|
|
||||||
|
void spawn_callback()
|
||||||
|
{
|
||||||
|
if (xbase->x_display) {
|
||||||
|
close(ConnectionNumber(xbase->x_display));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void tagmon(const Arg *arg)
|
||||||
|
{
|
||||||
|
if (!selmon->sel || !mons->next)
|
||||||
|
return;
|
||||||
|
sendmon(selmon->sel, dirtomon(arg->i));
|
||||||
|
}
|
||||||
|
|
||||||
|
void togglefloating(__attribute__((unused)) const Arg *arg)
|
||||||
|
{
|
||||||
|
if (!selmon->sel) return;
|
||||||
|
|
||||||
|
selmon->sel->state.is_floating =
|
||||||
|
!selmon->sel->state.is_floating || selmon->sel->state.is_fixed;
|
||||||
|
|
||||||
|
const int border_width = settings_get_border_width();
|
||||||
|
|
||||||
|
if (selmon->sel->state.is_floating) {
|
||||||
|
struct WinGeom win_geom = selmon->sel->state.geom;
|
||||||
|
|
||||||
|
win_geom.basic.sizes = sizes_create_from_args(
|
||||||
|
selmon->sel->state.geom.basic.sizes.w -
|
||||||
|
2 * (border_width - selmon->sel->state.geom.border_width),
|
||||||
|
selmon->sel->state.geom.basic.sizes.h -
|
||||||
|
2 * (border_width - selmon->sel->state.geom.border_width)
|
||||||
|
);
|
||||||
|
|
||||||
|
win_geom.border_width = border_width;
|
||||||
|
|
||||||
|
resize(selmon->sel, win_geom, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
arrange(selmon);
|
||||||
|
}
|
||||||
|
|
||||||
|
void zoom(__attribute__((unused)) const Arg *arg)
|
||||||
|
{
|
||||||
|
Client *c = selmon->sel;
|
||||||
|
|
||||||
|
if (!selmon->lt[selmon->sellt]->arrange
|
||||||
|
|| (selmon->sel && selmon->sel->state.is_floating))
|
||||||
|
return;
|
||||||
|
if (c == nexttiled(selmon->clients))
|
||||||
|
if (!c || !(c = nexttiled(c->next)))
|
||||||
|
return;
|
||||||
|
pop(c);
|
||||||
|
}
|
|
@ -0,0 +1,78 @@
|
||||||
|
#ifndef _DWM_INTERACTION_H
|
||||||
|
#define _DWM_INTERACTION_H
|
||||||
|
|
||||||
|
static void configborder(const Arg *arg);
|
||||||
|
static void configgap(const Arg *arg);
|
||||||
|
static void dorestart(const Arg *arg);
|
||||||
|
static void focusmon(const Arg *arg);
|
||||||
|
static void focusstack(const Arg *arg);
|
||||||
|
static void incnmaster(const Arg *arg);
|
||||||
|
static void killclient(const Arg *arg);
|
||||||
|
static void movemouse(const Arg *arg);
|
||||||
|
static void movestack(const Arg *arg);
|
||||||
|
static void quit(const Arg *arg);
|
||||||
|
static void resetnmaster(const Arg *arg);
|
||||||
|
static void resizemouse(const Arg *arg);
|
||||||
|
static void setlayout(const Arg *arg);
|
||||||
|
static void setmfact(const Arg *arg);
|
||||||
|
static void spawn(const Arg *arg);
|
||||||
|
static void tagmon(const Arg *arg);
|
||||||
|
static void togglefloating(const Arg *arg);
|
||||||
|
static void zoom(const Arg *arg);
|
||||||
|
|
||||||
|
static void spawn_callback();
|
||||||
|
|
||||||
|
#define MODKEY Mod4Mask
|
||||||
|
|
||||||
|
static Key keys[] = {
|
||||||
|
// WM
|
||||||
|
{ MODKEY|ControlMask|ShiftMask, XK_q, quit, {0} },
|
||||||
|
{ MODKEY|ControlMask|ShiftMask, XK_r, dorestart, {0} },
|
||||||
|
// Monitor
|
||||||
|
{ MODKEY, XK_bracketleft, focusmon, {.i = -1 } },
|
||||||
|
{ MODKEY, XK_bracketright, focusmon, {.i = +1 } },
|
||||||
|
{ MODKEY|ShiftMask, XK_bracketleft, tagmon, {.i = -1 } },
|
||||||
|
{ MODKEY|ShiftMask, XK_bracketright, tagmon, {.i = +1 } },
|
||||||
|
// Layout
|
||||||
|
{ MODKEY, XK_m, setlayout, {.v = &layouts[0]} }, // Monocle
|
||||||
|
{ MODKEY, XK_f, setlayout, {.v = &layouts[1]} }, // Floating
|
||||||
|
{ MODKEY, XK_t, setlayout, {.v = &layouts[2]} }, // Tile
|
||||||
|
{ MODKEY|ShiftMask, XK_t, setlayout, {.v = &layouts[3]} }, // Horizontile
|
||||||
|
{ MODKEY, XK_u, setlayout, {.v = &layouts[4]} }, // Centeredmaster
|
||||||
|
{ MODKEY, XK_space, setlayout, {0} },
|
||||||
|
{ MODKEY, XK_i, incnmaster, {.i = +1 } },
|
||||||
|
{ MODKEY|ShiftMask, XK_i, resetnmaster, {.i = 1 } },
|
||||||
|
{ MODKEY, XK_d, incnmaster, {.i = -1 } },
|
||||||
|
{ MODKEY|ShiftMask, XK_d, resetnmaster, {.i = 0 } },
|
||||||
|
// Stack
|
||||||
|
{ MODKEY, XK_j, focusstack, {.i = +1 } },
|
||||||
|
{ MODKEY, XK_k, focusstack, {.i = -1 } },
|
||||||
|
{ MODKEY|ShiftMask, XK_j, movestack, {.i = +1 } },
|
||||||
|
{ MODKEY|ShiftMask, XK_k, movestack, {.i = -1 } },
|
||||||
|
{ MODKEY, XK_Return, zoom, {0} },
|
||||||
|
// Window
|
||||||
|
{ MODKEY|ShiftMask, XK_x, killclient, {0} },
|
||||||
|
{ MODKEY|ShiftMask, XK_space, togglefloating, {0} },
|
||||||
|
// Appearance
|
||||||
|
{ MODKEY, XK_h, setmfact, {.f = -0.05} },
|
||||||
|
{ MODKEY, XK_l, setmfact, {.f = +0.05} },
|
||||||
|
{ MODKEY|Mod1Mask, XK_b, configborder, {.i = -1 } },
|
||||||
|
{ MODKEY|Mod1Mask|ShiftMask, XK_b, configborder, {.i = +1 } },
|
||||||
|
{ MODKEY|Mod1Mask, XK_g, configgap, {.i = -1 } },
|
||||||
|
{ MODKEY|Mod1Mask|ShiftMask, XK_g, configgap, {.i = +1 } },
|
||||||
|
// Starting applications
|
||||||
|
{ MODKEY, XK_z, spawn, {.v = "lock" } },
|
||||||
|
{ MODKEY, XK_slash, spawn, {.v = "menu" } },
|
||||||
|
{ MODKEY|ShiftMask, XK_slash, spawn, {.v = "term" } },
|
||||||
|
{ MODKEY|ShiftMask, XK_f, spawn, {.v = "firefox" } },
|
||||||
|
};
|
||||||
|
|
||||||
|
// click can be ClkClientWin, or ClkRootWin
|
||||||
|
static Button buttons[] = {
|
||||||
|
/* click event mask button function argument */
|
||||||
|
{ ClkClientWin, MODKEY, Button1, movemouse, {0} },
|
||||||
|
{ ClkClientWin, MODKEY, Button2, togglefloating, {0} },
|
||||||
|
{ ClkClientWin, MODKEY, Button3, resizemouse, {0} },
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // _DWM_INTERACTION_H
|
|
@ -0,0 +1,53 @@
|
||||||
|
static Window wmcheckwin = 0;
|
||||||
|
|
||||||
|
void wmcheckwin_create()
|
||||||
|
{
|
||||||
|
wmcheckwin = XCreateSimpleWindow(
|
||||||
|
xbase->x_display,
|
||||||
|
xbase->x_root,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
1,
|
||||||
|
1,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
0
|
||||||
|
);
|
||||||
|
|
||||||
|
XChangeProperty(
|
||||||
|
xbase->x_display,
|
||||||
|
wmcheckwin,
|
||||||
|
xbase->atoms->netatom[NetWMCheck],
|
||||||
|
XA_WINDOW,
|
||||||
|
32,
|
||||||
|
PropModeReplace,
|
||||||
|
(unsigned char*)&wmcheckwin,
|
||||||
|
1
|
||||||
|
);
|
||||||
|
XChangeProperty(
|
||||||
|
xbase->x_display,
|
||||||
|
wmcheckwin,
|
||||||
|
xbase->atoms->netatom[NetWMName],
|
||||||
|
xbase->atoms->utf8string,
|
||||||
|
8,
|
||||||
|
PropModeReplace,
|
||||||
|
(unsigned char*)
|
||||||
|
xbase->program_title,
|
||||||
|
strlen(xbase->program_title)
|
||||||
|
);
|
||||||
|
XChangeProperty(
|
||||||
|
xbase->x_display,
|
||||||
|
xbase->x_root,
|
||||||
|
xbase->atoms->netatom[NetWMCheck],
|
||||||
|
XA_WINDOW,
|
||||||
|
32,
|
||||||
|
PropModeReplace,
|
||||||
|
(unsigned char*)&wmcheckwin,
|
||||||
|
1
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
void wmcheckwin_destroy()
|
||||||
|
{
|
||||||
|
XDestroyWindow(xbase->x_display, wmcheckwin);
|
||||||
|
}
|
|
@ -0,0 +1,7 @@
|
||||||
|
#ifndef _DWM_WMCHECKWIN_H
|
||||||
|
#define _DWM_WMCHECKWIN_H
|
||||||
|
|
||||||
|
static void wmcheckwin_create();
|
||||||
|
static void wmcheckwin_destroy();
|
||||||
|
|
||||||
|
#endif // _DWM_WMCHECKWIN_H
|
Loading…
Reference in New Issue