Skip to content

Commit

Permalink
Add ability to move diagonally on virtual desktop
Browse files Browse the repository at this point in the history
See the comments added about configuring this in libinput-gestures.conf.

This is an enhancement added to address issue bulletmark#224.
  • Loading branch information
bulletmark committed Oct 16, 2019
1 parent dcdc33b commit bc69ac9
Show file tree
Hide file tree
Showing 7 changed files with 982 additions and 242 deletions.
5 changes: 4 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
README.html
.idea/
.vscode/
README.html
*.pyc
__pycache__
*~
5 changes: 4 additions & 1 deletion Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -27,13 +27,16 @@ uninstall:
@./libinput-gestures-setup -d "$(DESTDIR)" uninstall

check:
flake8 libinput-gestures
flake8 libinput-gestures internal internal-test
shellcheck $(SHELLCHECK_OPTS) libinput-gestures-setup list-version-hashes

doc: $(DOCOUT)

$(DOCOUT): $(DOC)
markdown $< >$@

test:
@./internal-test

clean:
rm -rf $(DOCOUT)
38 changes: 23 additions & 15 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -79,15 +79,23 @@ reading ..

The default gestures are in `/etc/libinput-gestures.conf`. If you want
to create your own custom gestures then copy that file to
`~/.config/libinput-gestures.conf` and edit it. The available gestures
are:

- swipe up (e.g. map to GNOME/KDE/etc move to next workspace)
- swipe down (e.g map to GNOME/KDE/etc move to prev workspace)
- swipe left (e.g. map to Web browser go forward)
- swipe right (e.g. map to Web browser go back)
- pinch in (e.g. map to GNOME open/close overview)
- pinch out (e.g. map to GNOME open/close overview)
`~/.config/libinput-gestures.conf` and edit it. There are many examples
and options described in that file. The available gestures are:

|Gesture |Example Mapping |
|------- |--------------- |
|`swipe up` |GNOME/KDE/etc move to next workspace |
|`swipe down` |GNOME/KDE/etc move to prev workspace |
|`swipe left` |Web browser go forward |
|`swipe right` |Web browser go back |
|`swipe left_up` |Jump to next open web browser tab |
|`swipe left_down` |Jump to previous open web browser tab |
|`swipe right_up` |Close current web browser tab |
|`swipe right_down` |Reopen and jump to last closed web browser tab |
|`pinch in` |GNOME open/close overview |
|`pinch out` |GNOME open/close overview |
|`pinch clockwise` ||
|`pinch anticlockwise` ||

NOTE: If you don't use "natural" scrolling direction for your touchpad
then you may want to swap the default left/right and up/down
Expand Down Expand Up @@ -223,12 +231,12 @@ configuration file but you can enable extended gestures which augment
the gestures listed above in CONFIGURATION. See the commented out
examples in `libinput-gestures.conf`.

- swipe right_up (e.g. jump to next open browser tab)
- swipe left_up (e.g. jump to previous open browser tab)
- swipe left_down (e.g. close current browser tab)
- swipe right_down (e.g. reopen and jump to last closed browser tab)
- pinch clockwise
- pinch anticlockwise
- `swipe right_up` (e.g. jump to next open browser tab)
- `swipe left_up` (e.g. jump to previous open browser tab)
- `swipe left_down` (e.g. close current browser tab)
- `swipe right_down` (e.g. reopen and jump to last closed browser tab)
- `pinch clockwise`
- `pinch anticlockwise`

So instead of just configuring the usual swipe up/down and left/right
each at 90 degrees separation, you can add the above extra 4 swipes to
Expand Down
108 changes: 108 additions & 0 deletions internal
Original file line number Diff line number Diff line change
@@ -0,0 +1,108 @@
#!/usr/bin/env python3
'Command line program to exercise/test/debug the _internal command.'
# Mark Blakeney, Oct 2019
import sys, importlib, argparse
from pathlib import Path

CMD = '_internal'
GESTURE = 'swipe'
PROG = Path(sys.argv[0]).resolve()
NAME = Path.cwd().name
CACHE = Path.home() / '.cache' / PROG.name

def import_path(path, add_to_path=False):
'Import given module path'
modname = Path(path).stem.replace('-', '_')
spec = importlib.util.spec_from_loader(modname,
importlib.machinery.SourceFileLoader(modname, path))
module = importlib.util.module_from_spec(spec)
spec.loader.exec_module(module)
if add_to_path:
sys.modules[modname] = module
return module

opt = argparse.ArgumentParser(description=__doc__)
opt.add_argument('-c', '--conffile',
help='alternative configuration file')
opt.add_argument('-i', '--initial', type=int,
help='initial desktop')
opt.add_argument('-C', '--cols', type=int, default=1,
help='number of columns')
opt.add_argument('-t', '--text', action='store_true',
help='output desktop change in text')
opt.add_argument('-n', '--nocache', action='store_true',
help='do not use cache')
opt.add_argument('num', type=int,
help='number of desktops')
opt.add_argument('action', nargs='?',
help='action to perform')
opt.add_argument('-d', '--display', type=int,
help=argparse.SUPPRESS)
opt.add_argument('-s', '--set', type=int, help=argparse.SUPPRESS)
args = opt.parse_args()

def showgrid(pos, num, cols):
print()
for i in range(num):
end = '\n' if (i % cols) == (cols - 1) else ''
if i == pos:
print(' {:02} '.format(i), end=end)
else:
print(' ** ', end=end)
if end != '\n':
print()

if args.set is not None:
print(args.set)
sys.exit(0)

if args.display is not None:
for i in range(args.num):
print('{} {} -'.format(i, '*' if i == args.display else '-'))
sys.exit(0)

if args.initial is None:
if args.nocache:
opt.error('Initial value must be specified')
if not CACHE.exists():
opt.error('Need initial desktop specified')
start = int(CACHE.read_text().strip())
else:
start = args.initial

lg = import_path(NAME)
icmd = lg.internal_commands[CMD]

icmd.CMDLIST = '{} -d {} {}'.format(PROG, start, args.num).split()
icmd.CMDSET = '{} {} -s'.format(PROG, args.num).split()

lg.read_conf(args.conffile, NAME + '.conf')
motions = lg.handlers[GESTURE.upper()].motions
actions = {k: v for k, v in motions.items() if isinstance(v, icmd)}

if not args.action or args.action not in actions:
opt.error('action must be one of {}'.format(list(actions.keys())))

cmd = motions[args.action]
print('Command "{} {} is "{}"'.format(GESTURE, args.action, cmd))
res = cmd.run(block=True)

if res:
end = int(res.strip())
if not args.nocache:
CACHE.write_text(str(end))
else:
end = start

if end < 0 or end >= args.num:
sys.exit('Desktop change from {} to {}, out of range 0 to <{}!'.format(
start, end, args.num))

if args.text:
if start != end:
print('Desktop change from {} to {}'.format(start, end))
else:
print('No change')
else:
showgrid(start, args.num, args.cols)
showgrid(end, args.num, args.cols)
Loading

0 comments on commit bc69ac9

Please sign in to comment.