summaryrefslogtreecommitdiff
path: root/odk/examples/python/Miscellaneous/InputEvents.py
blob: 8dc443e2f6d2d179cac11b395ffedb6c641f7b4c (plain)
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
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
# -*- tab-width: 4; indent-tabs-mode: nil; py-indent-offset: 4 -*-
#
# This file is part of the LibreOffice project.
#
# This Source Code Form is subject to the terms of the Mozilla Public
# License, v. 2.0. If a copy of the MPL was not distributed with this
# file, You can obtain one at https://mozilla.org/MPL/2.0/.
#

import uno
import unohelper
from com.sun.star.awt import XKeyHandler
from com.sun.star.awt import XKeyListener
from com.sun.star.awt import XMouseClickHandler
from com.sun.star.awt import XMouseMotionHandler
from com.sun.star.awt import XMouseListener
from com.sun.star.awt import XMouseMotionListener
from com.sun.star.accessibility import AccessibleRole


"""
This example illustrates how to register to keyboard or mouse events.

There are two families of interfaces for this, called Listeners and Handlers.
In many cases the Handlers are easier to use and provide more flexibility. But
sometimes it's necessary to use the Listeners, as being shown below.

The Listeners usually need to be added exactly to the correct widget. So this
example adds them recursively them to all widgets below the given one.
"""


SOFFICE_CONNECTION_URI = "uno:socket,host=localhost,port=2083;urp;StarOffice.ComponentContext"


def demo():
    # Connect to LibreOffice process
    localComponentContext = uno.getComponentContext()
    localServiceManager = localComponentContext.getServiceManager()
    resolver = localServiceManager.createInstanceWithContext("com.sun.star.bridge.UnoUrlResolver", localComponentContext)
    remoteComponentContext = resolver.resolve(SOFFICE_CONNECTION_URI)

    # Get the currently opened view context.
    remoteServiceManager = remoteComponentContext.getServiceManager()
    desktop = remoteServiceManager.createInstance("com.sun.star.frame.Desktop")
    xComponent = desktop.getCurrentComponent()  # e.g. SwXTextDocument, ScModelObj, SdXImpressDocument
    if "com.sun.star.document.OfficeDocument" not in xComponent.getSupportedServiceNames():
        print("No OfficeDocument opened.")
        exit(1)
    else:
        handler = MyXKeyMouseClickMotionHandler("handler")
        # Events in the document view area. Not in the surrounding UI.
        xController = xComponent.getCurrentController()  # xModel.getCurrentController()
        xController.addKeyHandler(handler)         # XUserInputInterception.addKeyHandler()
        xController.addMouseClickHandler(handler)  # XUserInputInterception.addMouseClickHandler()

        listener = MyXKeyMouseClickMotionHandler("listener")
        # TODO: Register to e.value.Source of Handler events.
        #       That's the correct source.
        xWindow = xController.ComponentWindow
        # In writer we're usually looking for:
        #   xWindow.Windows[0].Windows[0]
        recursive_windows("", xWindow, lambda subXWindow: (
                subXWindow.addKeyListener(listener),
                subXWindow.addMouseListener(listener),
                #subXWindow.addMouseMotionListener(listener),  # very much events
            ))

        # Maybe the event handlers can also be registered via one of the objects
        # this function iterates through. But currently this function just
        # prints the accessible roles of the objects.
        #recursive_acc_ctx("", xWindow.AccessibleContext.AccessibleParent);
        #recursive_acc_ctx("", xWindow);

        input("Waiting for events. Press Enter to quit...\n")


def recursive_acc_ctx(path, obj):
    print("recursive_acc_ctx: " + path + find_accessible_role(obj.getAccessibleContext().getAccessibleRole()))
    for i in range(obj.getAccessibleContext().AccessibleChildCount):
        recursive_acc_ctx(path+str(i)+": ", obj.getAccessibleContext().getAccessibleChild(i))


def recursive_windows(path, xWindow, func):
    print("recursive_windows: " + path + find_accessible_role(xWindow.getAccessibleContext().getAccessibleRole()))
    func(xWindow)
    try:
        windows = xWindow.getWindows()  # XVclContainer.getWindows()
    except Exception:
        return
    for i in range(len(windows)):
        subXWindow = windows[i]
        recursive_windows(path+str(i)+": ", subXWindow, func)


def find_accessible_role(role_int):
    for role_name in dir(AccessibleRole):
        if role_int == eval("AccessibleRole." + role_name):
            return role_name


class MyXKeyMouseClickMotionHandler(unohelper.Base, XKeyHandler, XKeyListener, XMouseClickHandler, XMouseMotionHandler, XMouseListener, XMouseMotionListener):
    def __init__(self, name):  # XKeyHandler, XKeyListener
        self.name = name
    def keyPressed(self, e):  # XKeyHandler, XKeyListener
        self.key_evt(e, "pressed")
        return False  # False: don't consume (run other event handlers)
    def keyReleased(self, e):
        self.key_evt(e, "released")
        return False
    def mousePressed(self, e):  # XMouseClickHandler, XMouseListener
        self.mouse_evt(e, "pressed")
        return False
    def mouseReleased(self, e):  # XMouseClickHandler, XMouseListener
        self.mouse_evt(e, "released")
        return False
    def mouseEntered(self, e):  # XMouseListener
        self.mouse_evt(e, "entered")
        return False
    def mouseExited(self, e):  # XMouseListener
        self.mouse_evt(e, "exited")
        return False
    def mouseDragged(self, e):  # XMouseMotionHandler, XMouseMotionListener
        self.mouse_evt(e, "dragged")
        return False
    def mouseMoved(self, e):  # XMouseMotionHandler, XMouseMotionListener
        self.mouse_evt(e, "moved")
        return False

    def disposing(self, s):
        print(self.name + "# disposing")
    def key_evt(self, e, action):
        #print(self.name + "# key "+action+": " + str(e));  # very much output
        print(self.name + "# key "+action+" (code: " + str(e.value.KeyCode.real) + "): " + e.value.KeyChar.value)
    def mouse_evt(self, e, action):
        #print(self.name + "# mouse "+action+": " + str(e));  # very much output
        print(self.name + "# mouse "+action+": Modifiers: "+str(e.value.Modifiers)+"; Buttons: "+str(e.value.Buttons)+"; X: "+str(e.value.X)+"; Y: "+str(e.value.Y)+"; ClickCount: "+str(e.value.ClickCount)+"; PopupTrigger: "+str(e.value.PopupTrigger))


demo()


# vim: set shiftwidth=4 softtabstop=4 expandtab: