joonis Logo

Bind media keys to mouse buttons

A small script to bind XF86Audio media keys to extra mouse buttons.

Depending on the pressed thumb button you can change the volume or track by scrolling the mouse wheel. If the mouse wheel is not scrolled, the volume is muted or the current track is paused.

mousemedia.py [4.10 KB]
  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
#!/usr/bin/python
# -*- coding: utf-8 -*-
#
#  mousemedia.py
#  Binding of XF86Audio keys to mouse buttons
#
#  Copyright (c) 2016 joonis new media
#  Author: Thimo Kraemer <thimo.kraemer@joonis.de>
#
#  This program is free software; you can redistribute it and/or modify
#  it under the terms of the GNU General Public License as published by
#  the Free Software Foundation; either version 2 of the License, or
#  (at your option) any later version.
#
#  This program is distributed in the hope that it will be useful,
#  but WITHOUT ANY WARRANTY; without even the implied warranty of
#  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
#  GNU General Public License for more details.
#
#  You should have received a copy of the GNU General Public License
#  along with this program; if not, write to the Free Software
#  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
#  MA 02110-1301, USA.

from Xlib import X
from Xlib.display import Display
from Xlib.ext.xtest import fake_input

#######################################################################
# Configuration

# Pointer mapping
POINTER_MAPPING = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13]

# Which buttons to bind
volume_button = POINTER_MAPPING[7] # usually first thumb button
track_button = POINTER_MAPPING[8] # usually second thumb button

# End of configuration
#######################################################################

# Verify to have a usable mouse
assert 1 in POINTER_MAPPING[:3]
assert 2 in POINTER_MAPPING[:3]
assert 3 in POINTER_MAPPING[:3]
assert POINTER_MAPPING.index(volume_button) not in (0, 2, 3, 4)
assert POINTER_MAPPING.index(track_button) not in (0, 2, 3, 4)

display = Display()
root = display.screen().root

def tap_key(keycode):
    fake_input(display, X.KeyPress, keycode)
    fake_input(display, X.KeyRelease, keycode)
    display.sync()

def keysym_to_keycode(keysym):
    keycode = display.keysym_to_keycode(keysym)
    if not keycode:
        raise ValueError('no keycode found for keysym %s' % keysym)
    return keycode

XF86AudioLowerVolume = keysym_to_keycode(0x1008FF11)
XF86AudioMute = keysym_to_keycode(0x1008FF12)
XF86AudioRaiseVolume = keysym_to_keycode(0x1008FF13)
XF86AudioPlay = keysym_to_keycode(0x1008FF14)
XF86AudioPrev = keysym_to_keycode(0x1008FF16)
XF86AudioNext = keysym_to_keycode(0x1008FF17)

def run():
    display.set_pointer_mapping(POINTER_MAPPING)
    scroll_buttons = POINTER_MAPPING[3:5]
    # Grab buttons
    for button in (volume_button, track_button):
        root.grab_button(button, X.AnyModifier, True,
            X.ButtonPressMask | X.ButtonReleaseMask,
            X.GrabModeAsync, X.GrabModeAsync, 0, 0)

    volume_pressed = False
    track_pressed = False
    volume_changed = False
    track_changed = False
    
    try:
        while True:
            event = root.display.next_event()
            if event.type not in (X.ButtonPress, X.ButtonRelease):
                continue
                
            button = event.detail
            pressed = (event.type == X.ButtonPress)
            
            if button == volume_button:
                volume_pressed = pressed
                if not (pressed or volume_changed):
                    tap_key(XF86AudioMute)
                volume_changed = False
            elif button == track_button:
                track_pressed = pressed
                if not (pressed or track_changed):
                    tap_key(XF86AudioPlay)
                track_changed = False
            elif button in scroll_buttons and pressed:
                if volume_pressed:
                    volume_changed = True
                    tap_key(button == scroll_buttons[0] and
                        XF86AudioRaiseVolume or XF86AudioLowerVolume)
                elif track_pressed:
                    track_changed = True
                    tap_key(button == scroll_buttons[0] and
                        XF86AudioPrev or XF86AudioNext)
    finally:
        # Ungrab buttons
        for button in (volume_button, track_button):
            root.ungrab_button(button, X.AnyModifier)

if __name__ == '__main__':
    try:
        run()
    except KeyboardInterrupt:
        pass

Kann ich
  Ihnen helfen?


Schreiben Sie mir
doch einfach unter
giraffe@joonis.de