root/sx-clientbuttons/sxclientbuttons.py @ 5e5ff8c70c8971fb4a242ece716271ff9f3b7999

Revision 5e5ff8c70c8971fb4a242ece716271ff9f3b7999, 3.9 KB (checked in by dunk <dunk@…>, 15 months ago)

sx-clientbuttons: bind buttons to client.window instead of actor - i think that makes more sense

  • Property mode set to 100644
Line 
1# Copyright (c) 2008-2009, samurai-x.org
2# All rights reserved.
3#
4# Redistribution and use in source and binary forms, with or without
5# modification, are permitted provided that the following conditions are met:
6#     * Redistributions of source code must retain the above copyright
7#       notice, this list of conditions and the following disclaimer.
8#     * Redistributions in binary form must reproduce the above copyright
9#       notice, this list of conditions and the following disclaimer in the
10#       documentation and/or other materials provided with the distribution.
11#     * Neither the name of the samurai-x.org nor the
12#       names of its contributors may be used to endorse or promote products
13#       derived from this software without specific prior written permission.
14#
15# THIS SOFTWARE IS PROVIDED BY SAMURAI-X.ORG ``AS IS'' AND ANY
16# EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
17# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
18# DISCLAIMED. IN NO EVENT SHALL SAMURAI-X.ORG  BE LIABLE FOR ANY
19# DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
20# (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
21# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
22# ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
23# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
24# SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
25
26"""
27    sx-clientbuttons is a plugin that enables you to bind mouse button
28    and modifier key combinations to an action.
29
30    Configuration
31    -------------
32
33    .. attribute:: clientbuttons.bindings
34
35        Dictionary of button/modifier (:ref:`buttonstrokes`): action.
36        For example::
37   
38            'clientbuttons.bindings': {
39                'Meta+1': 'moveresize.move',
40                'Meta+3': 'moveresize.resize',
41            }
42
43"""
44
45import logging
46log = logging.getLogger(__name__)
47
48from samuraix import config
49from samuraix.plugin import Plugin
50from samuraix.util import parse_buttonstroke
51
52from ooxcb.protocol import xproto
53from ooxcb.protocol.xproto import EventMask
54
55from sxactions import ActionInfo
56
57
58class SXClientButtons(Plugin):
59    """ Plugin to allow binding mouse actions to actions """
60
61    key = 'clientbuttons'
62
63    def __init__(self, app):
64        self.app = app
65        app.push_handlers(self)
66        self.bindings = {}
67
68    def on_load_config(self, config):
69        for stroke, action in config.get('clientbuttons.bindings', {}).iteritems():
70            buttonstroke = parse_buttonstroke(stroke)
71            self.bindings[buttonstroke] = action
72
73    def on_ready(self, app):
74        for screen in app.screens:
75            screen.push_handlers(self)
76
77            for client in screen.clients:
78                self.on_new_client(screen, client)
79
80    def on_new_client(self, screen, client):
81        def on_button_press(evt):
82            stroke = (evt.state, evt.detail)
83            if stroke in self.bindings:
84                info = ActionInfo(screen=self.app.get_screen_by_root(evt.root),
85                    x=evt.event_x, y=evt.event_y,
86                    client=client)
87                self.app.plugins['actions'].emit(self.bindings[stroke], info)
88
89        # grab the specific button and modifier to allow the app to keep working!
90        for modifier, button in self.bindings.iterkeys():
91            client.window.grab_button(EventMask.ButtonPress,
92                button,
93                modifier,
94                False,
95                xproto.GrabMode.Sync,
96                xproto.GrabMode.Sync
97            )
98
99        client.window.push_handlers(on_button_press=on_button_press)
100
101    def on_unmanage_client(self, screen, client):
102        # tidy up properly, but only if the actor exists
103        if client.actor.valid:
104            for modifier, button in self.bindings.iterkeys():
105                client.window.ungrab_button(button, modifier)
106
107
Note: See TracBrowser for help on using the browser.