Skip to content

Commit

Permalink
Mouse support! Move, focus, and resize windows with the mouse!
Browse files Browse the repository at this point in the history
  • Loading branch information
tudurom committed Aug 10, 2017
1 parent 7056d49 commit 4ff4da0
Show file tree
Hide file tree
Showing 10 changed files with 196 additions and 28 deletions.
91 changes: 78 additions & 13 deletions client.c
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,9 @@ static bool fn_hex(uint32_t *, int, char **);
static bool fn_position(uint32_t *, int, char **);
static bool fn_gap(uint32_t *, int, char **);
static bool fn_direction(uint32_t *, int, char **);
static bool fn_pac(uint32_t *, int, char **);
static bool fn_mod(uint32_t *, int, char **);
static bool fn_button(uint32_t *, int, char **);

static void usage(char *, int);
static void version(void);
Expand All @@ -43,6 +46,7 @@ struct Command {
struct ConfigEntry {
char *key;
enum IPCConfig config;
int argc;
bool (*handler)(uint32_t *, int, char **);
};

Expand Down Expand Up @@ -79,19 +83,22 @@ static struct Command c[] = {
};

static struct ConfigEntry configs[] = {
{ "border_width" , IPCConfigBorderWidth , fn_naturals },
{ "color_focused" , IPCConfigColorFocused , fn_hex },
{ "color_unfocused" , IPCConfigColorUnfocused , fn_hex },
{ "gap_width" , IPCConfigGapWidth , fn_gap },
{ "grid_gap_width" , IPCConfigGridGapWidth , fn_naturals },
{ "cursor_position" , IPCConfigCursorPosition , fn_position },
{ "groups_nr" , IPCConfigGroupsNr , fn_naturals },
{ "enable_sloppy_focus" , IPCConfigEnableSloppyFocus , fn_bool },
{ "enable_resize_hints" , IPCConfigEnableResizeHints , fn_bool },
{ "sticky_windows" , IPCConfigStickyWindows , fn_bool },
{ "enable_borders" , IPCConfigEnableBorders , fn_bool },
{ "enable_last_window_focusing", IPCConfigEnableLastWindowFocusing, fn_bool },
{ "apply_settings" , IPCConfigApplySettings , fn_bool },
{ "border_width" , IPCConfigBorderWidth , 1 , fn_naturals },
{ "color_focused" , IPCConfigColorFocused , 1 , fn_hex },
{ "color_unfocused" , IPCConfigColorUnfocused , 1 , fn_hex },
{ "gap_width" , IPCConfigGapWidth , 2 , fn_gap },
{ "grid_gap_width" , IPCConfigGridGapWidth , 1 , fn_naturals },
{ "cursor_position" , IPCConfigCursorPosition , 1 , fn_position },
{ "groups_nr" , IPCConfigGroupsNr , 1 , fn_naturals },
{ "enable_sloppy_focus" , IPCConfigEnableSloppyFocus , 1 , fn_bool },
{ "enable_resize_hints" , IPCConfigEnableResizeHints , 1 , fn_bool },
{ "sticky_windows" , IPCConfigStickyWindows , 1 , fn_bool },
{ "enable_borders" , IPCConfigEnableBorders , 1 , fn_bool },
{ "enable_last_window_focusing", IPCConfigEnableLastWindowFocusing, 1 , fn_bool },
{ "apply_settings" , IPCConfigApplySettings , 1 , fn_bool },
{ "pointer_actions" , IPCConfigPointerActions , 3 , fn_pac },
{ "pointer_modifier" , IPCConfigPointerModifier , 1 , fn_mod },
{ "click_to_focus" , IPCConfigClickToFocus , 1 , fn_button },
};

/*
Expand Down Expand Up @@ -171,6 +178,8 @@ fn_config(uint32_t *data, int argc, char **argv) {
i++;

if (i < NR_IPC_CONFIGS) {
if (configs[i].argc != argc - 1)
errx(EXIT_FAILURE, "too many or not enough arguments. Want: %d", configs[i].argc);
data[0] = configs[i].config;
status = (configs[i].handler)(data + 1, argc - 1, argv + 1);

Expand Down Expand Up @@ -221,6 +230,62 @@ fn_direction(uint32_t *data, int argc, char **argv)
return true;
}

static bool
fn_pac(uint32_t *data, int argc, char **argv)
{
for (int i = 0; i < argc; i++) {
char *pac = argv[i];
if (strcasecmp(pac, "nothing") == 0)
data[i] = POINTER_ACTION_NOTHING;
else if (strcasecmp(pac, "focus") == 0)
data[i] = POINTER_ACTION_FOCUS;
else if (strcasecmp(pac, "move") == 0)
data[i] = POINTER_ACTION_MOVE;
else if (strcasecmp(pac, "resize_corner") == 0)
data[i] = POINTER_ACTION_RESIZE_CORNER;
else if (strcasecmp(pac, "resize_side") == 0)
data[i] = POINTER_ACTION_RESIZE_SIDE;
else
return false;
}

return true;
}
static bool
fn_mod(uint32_t *data, int argc, char **argv)
{
(void)(argc);
if (strcasecmp(argv[0], "alt") == 0)
data[0] = XCB_MOD_MASK_1;
else if (strcasecmp(argv[0], "super") == 0)
data[0] = XCB_MOD_MASK_4;
else
return false;

return true;
}
static bool
fn_button(uint32_t *data, int argc, char **argv)
{
char *btn = argv[0];
(void)(argc);

if (strcasecmp(btn, "left") == 0)
data[0] = 1;
else if (strcasecmp(btn, "middle") == 0)
data[0] = 2;
else if (strcasecmp(btn, "right") == 0)
data[0] = 3;
else if (strcasecmp(btn, "none") == 0)
data[0] = UINT32_MAX;
else if (strcasecmp(btn, "any") == 0)
data[0] = 0;
else
return false;

return true;
}

static bool
fn_position(uint32_t *data, int argc, char **argv)
{
Expand Down
5 changes: 3 additions & 2 deletions config.h
Original file line number Diff line number Diff line change
Expand Up @@ -45,10 +45,11 @@
#define DEFAULT_MIDDLE_BUTTON_ACTION POINTER_ACTION_RESIZE_SIDE
#define DEFAULT_RIGHT_BUTTON_ACTION POINTER_ACTION_RESIZE_CORNER

/* default pointer modifier (super key) */
/* default pointer modifier (super key). Set to XCB_MOD_MASK_1 for alt */
#define POINTER_MODIFIER XCB_MOD_MASK_4

/* default mouse button for click to focus. -1 for none */
/* default mouse button for click to focus. -1 for none, 0 for any
1, 2, 3 for left-click, middle-click, right-click */
#define CLICK_TO_FOCUS_BUTTON 0

#endif
4 changes: 4 additions & 0 deletions examples/windowchefrc
Original file line number Diff line number Diff line change
Expand Up @@ -12,3 +12,7 @@ waitron wm_config enable_sloppy_focus true
waitron wm_config sticky_windows false
waitron wm_config enable_borders true
waitron wm_config enable_last_window_focusing true
waitron wm_config apply_settings true
waitron wm_config pointer_actions move resize_side resize_corner
waitron wm_config pointer_modifier super
waitron wm_config click_to_focus any
3 changes: 3 additions & 0 deletions ipc.h
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,9 @@ enum IPCConfig {
IPCConfigEnableBorders,
IPCConfigEnableLastWindowFocusing,
IPCConfigApplySettings,
IPCConfigPointerActions,
IPCConfigPointerModifier,
IPCConfigClickToFocus,
NR_IPC_CONFIGS
};

Expand Down
29 changes: 28 additions & 1 deletion man/waitron.1
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
.\" generated with Ronn/v0.7.3
.\" https://github.com/rtomayko/ronn/tree/0.7.3
.
.TH "WAITRON" "1" "July 2017" "Windowchef" "Windowchef Manual"
.TH "WAITRON" "1" "August 2017" "Windowchef" "Windowchef Manual"
.
.SH "NAME"
\fBwaitron\fR \- A client for windowchef(1)
Expand Down Expand Up @@ -39,6 +39,18 @@ false values: \fBfalse\fR | \fBf\fR | \fBno\fR | \fBn\fR | \fB0\fR
\fBDIRECTION\fR
\fBup\fR | \fBdown\fR | \fBleft\fR | \fBright\fR | \fBnorth\fR | \fBsouth\fR | \fBwest\fR | \fBeast\fR
.
.TP
\fBPOINTER_ACTION\fR
\fBnothing\fR | \fBfocus\fR | \fBmove\fR | \fBresize_corner\fR | \fBresize_side\fR
.
.TP
\fBPOINTER_MODIFIER\fR
\fBalt\fR | \fBsuper\fR
.
.TP
\fBMOUSE_BUTTON\fR
\fBany\fR | \fBnone\fR | \fBleft\fR | \fBmiddle\fR | \fBright\fR
.
.SH "COMMANDS"
.
.TP
Expand Down Expand Up @@ -234,7 +246,22 @@ If true, when the currently focused window is unmapped or closed, \fBwindowchef\
\fBapply_settings\fR \fIBOOL\fR
If true, then some settings will be applied on all windows instead of newly created windows\. True by default\.
.
.TP
\fBpointer_actions\fR \fIPOINTER_ACTION\fR \fIPOINTER_ACTION\fR \fIPOINTER_ACTION\fR
Sets the action that should be done whenever the modifier key and the corresponding button are clicked at the same time on the window\. There are 3 actions for three mouse buttons: left, middle and right\.
.
.TP
\fBpointer_modifier\fR \fIPOINTER_MODIFIER\fR
Set the modifier for pointer actions\.
.
.TP
\fBclick_to_focus\fR \fIMOUSE_BUTTON\fR
Set the mouse button that focuses the hovered window when clicked\.
.
.SH "SEE ALSO"

.
.P
windowchef(1), sxhkd(1), wmutils(1), pfw(1), lsw(1), chwb2(1), lemonbar(1)
.
.SH "REPORTING BUGS"
Expand Down
14 changes: 11 additions & 3 deletions man/waitron.1.html

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

19 changes: 19 additions & 0 deletions man/waitron.1.md
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,15 @@ anything on `stdout`.
* `DIRECTION`:
`up` | `down` | `left` | `right` | `north` | `south` | `west` | `east`

* `POINTER_ACTION`:
`nothing` | `focus` | `move` | `resize_corner` | `resize_side`

* `POINTER_MODIFIER`:
`alt` | `super`

* `MOUSE_BUTTON`:
`any` | `none` | `left` | `middle` | `right`

## COMMANDS

* `window_move` <x> <y>:
Expand Down Expand Up @@ -206,6 +215,16 @@ are:
If true, then some settings will be applied on all windows instead of newly created windows.
True by default.

* `pointer_actions` <POINTER_ACTION> <POINTER_ACTION> <POINTER_ACTION>:
Sets the action that should be done whenever the modifier key and the corresponding button
are clicked at the same time on the window. There are 3 actions for three mouse buttons:
left, middle and right.

* `pointer_modifier` <POINTER_MODIFIER>:
Set the modifier for pointer actions.

* `click_to_focus` <MOUSE_BUTTON>:
Set the mouse button that focuses the hovered window when clicked.
## SEE ALSO

windowchef(1), sxhkd(1), wmutils(1), pfw(1), lsw(1), chwb2(1), lemonbar(1)
Expand Down
2 changes: 1 addition & 1 deletion man/windowchef.1
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
.\" generated with Ronn/v0.7.3
.\" https://github.com/rtomayko/ronn/tree/0.7.3
.
.TH "WINDOWCHEF" "1" "July 2017" "Windowchef" "Windowchef Manual"
.TH "WINDOWCHEF" "1" "August 2017" "Windowchef" "Windowchef Manual"
.
.SH "NAME"
\fBwindowchef\fR \- A stacking window cooker
Expand Down
2 changes: 1 addition & 1 deletion man/windowchef.1.html

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

55 changes: 48 additions & 7 deletions wm.c
Original file line number Diff line number Diff line change
Expand Up @@ -199,6 +199,8 @@ static void window_grab_button(xcb_window_t, uint8_t, uint16_t);
static bool pointer_grab(enum pointer_action);
static enum resize_handle get_handle(struct client *, xcb_point_t, enum pointer_action);
static void track_pointer(struct client *, enum pointer_action, xcb_point_t);
static void grab_buttons(void);
static void ungrab_buttons(void);

static void usage(char *);
static void version(void);
Expand All @@ -214,6 +216,7 @@ cleanup(void)
{
xcb_set_input_focus(conn, XCB_NONE, XCB_INPUT_FOCUS_POINTER_ROOT,
XCB_CURRENT_TIME);
ungrab_buttons();
if (ewmh != NULL)
xcb_ewmh_connection_wipe(ewmh);
if (win_list != NULL)
Expand Down Expand Up @@ -2993,6 +2996,26 @@ ipc_wm_config(uint32_t *d)
case IPCConfigApplySettings:
conf.apply_settings = d[1];
break;
case IPCConfigPointerActions:
for (int i = 0; i < NR_BUTTONS; i++) {
conf.pointer_actions[i] = d[i + 1];
}
ungrab_buttons();
grab_buttons();
break;
case IPCConfigPointerModifier:
conf.pointer_modifier = d[1];
ungrab_buttons();
grab_buttons();
break;
case IPCConfigClickToFocus:
if (d[1] == UINT32_MAX)
conf.click_to_focus = -1;
else
conf.click_to_focus = d[1];
ungrab_buttons();
grab_buttons();
break;
default:
DMSG("!!! unhandled config key %d\n", key);
break;
Expand Down Expand Up @@ -3110,13 +3133,13 @@ pointer_grab(enum pointer_action pac)
if (client == NULL)
return true;

raise_window(client->window);
if (pac == POINTER_ACTION_FOCUS) {
DMSG("grabbing pointer to focus on 0x%08x\n", client->window);
if (client != focused_win) {
set_focused(client);
return true;
}
raise_window(client->window);
return false;
}

Expand Down Expand Up @@ -3183,12 +3206,6 @@ get_handle(struct client *client, xcb_point_t pos, enum pointer_action pac)
else
handle = HANDLE_BOTTOM_RIGHT;
}
switch (handle) {
case HANDLE_TOP_LEFT: DMSG("top left\n"); break;
case HANDLE_TOP_RIGHT: DMSG("top right\n"); break;
case HANDLE_BOTTOM_LEFT: DMSG("bottom left\n"); break;
case HANDLE_BOTTOM_RIGHT: DMSG("bottom right\n"); break;
}
} else {
handle = HANDLE_TOP_LEFT;
}
Expand Down Expand Up @@ -3283,6 +3300,30 @@ track_pointer(struct client *client, enum pointer_action pac, xcb_point_t pos)
xcb_ungrab_pointer(conn, XCB_CURRENT_TIME);
}

static void
grab_buttons(void)
{
struct list_item *item;
struct client *client;

for (item = win_list; item != NULL; item = item->next) {
client = item->data;
window_grab_buttons(client->window);
}
}

static void
ungrab_buttons(void)
{
struct list_item *item;
struct client *client;

for (item = win_list; item != NULL; item = item->next) {
client = item->data;
xcb_ungrab_button(conn, XCB_BUTTON_INDEX_ANY, client->window, XCB_MOD_MASK_ANY);
}
}

static void
usage(char *name)
{
Expand Down

0 comments on commit 4ff4da0

Please sign in to comment.