Узнайте состояние кнопки мыши через Xlib в Python - PullRequest
0 голосов
/ 05 марта 2019

Я могу определить текущее положение указателя мыши с помощью:

from Xlib.display import Display
display = Display()
qp = display.screen().root.query_pointer()
print(qp.root_x, qp.root_y)

Как мне получить текущие состояния кнопок мыши, такие как нажатие / отпускание левой / правой кнопки также через Xlib?(Или если это невозможно - почему бы и нет?)

Ответы [ 2 ]

0 голосов
/ 06 июня 2019

Ваше окно X должно поддерживать расширение XInput.Real X работает, но переход к кнопке мыши не работает, если X-сервер не поддерживает такое расширение, как VNC-сервер.

Если X-сервер поддерживает его, вы можете перейти в состояние мыши следующим образом:

from Xlib.display import Display
from Xlib.ext import xinput

display = Display()

import time

while True:
    buttons = []

    for device_info in display.xinput_query_device(xinput.AllDevices).devices:
        if not device_info.enabled:
            continue
        if xinput.ButtonClass not in [ device_class.type for device_class in device_info.classes ]:
            continue
        buttons.append(device_info)

    for button in buttons:
        for device_class in button.classes:
            if xinput.ButtonClass == device_class.type:
                if device_class.state[0]:
                    print('Device {name} - Primary button down'.format(name=button.name))
    time.sleep(1)

Я не уверен на 100%, поскольку документы нигде не найдены, но я почти уверен, что device_class.state [0] является основным (левая кнопка), 1 - средним, а 2 -правая кнопка.

Вы, вероятно, можете узнать спецификацию назначения номера кнопки здесь

РЕДАКТИРОВАТЬ:

Почему есть два цикла for - Сначала я написалчасть «кнопок» за пределами вечной петли.Но, «эй, вы можете подключить мышь в любое время».

Вы обнаружите, что есть много устройств, включая «виртуальные».На ноутбуке тачпад также работает как кнопка, поэтому в вашем приложении, если вы хотите узнать настоящие кнопки мыши, вам, возможно, придется выбрать устройство по названию.Опять же, нет хороших документов, поэтому вам, вероятно, придется расшифровать объект класса устройства.Вы можете найти xinput как /usr/lib/python3/dist-packages/Xlib/ext/xinput.py.(Отрегулируйте его соответствующим образом, если вы используете Python2.) Удачи.

0 голосов
/ 31 мая 2019

Если для X-сервера включено расширение RECORD, его можно использовать для определения текущего состояния кнопки мыши.Тем не менее, он не будет предоставлять информацию напрямую: отдельные события кнопок вверх и вниз должны отслеживаться.

Это также означает, что текущее состояние будет известно только после того, как программа получит хотя бы одно первоесобытие при нажатии кнопки мыши вверх или вниз.

python-xlib предоставляет следующий пример сценария на https://github.com/python-xlib/python-xlib/blob/master/examples/record_demo.py

from __future__ import print_function

import sys
import os

# Change path so we find Xlib
sys.path.append(os.path.join(os.path.dirname(__file__), '..'))

from Xlib import X, XK, display
from Xlib.ext import record
from Xlib.protocol import rq

local_dpy = display.Display()
record_dpy = display.Display()


def lookup_keysym(keysym):
    for name in dir(XK):
        if name[:3] == "XK_" and getattr(XK, name) == keysym:
            return name[3:]
    return "[%d]" % keysym


def record_callback(reply):
    if reply.category != record.FromServer:
        return
    if reply.client_swapped:
        print("* received swapped protocol data, cowardly ignored")
        return
    if not len(reply.data) or reply.data[0] < 2:
        # not an event
        return

    data = reply.data
    while len(data):
        event, data = rq.EventField(None).parse_binary_value(
            data, record_dpy.display, None, None)

        if event.type in [X.KeyPress, X.KeyRelease]:
            pr = event.type == X.KeyPress and "Press" or "Release"

            keysym = local_dpy.keycode_to_keysym(event.detail, 0)
            if not keysym:
                print("KeyCode%s" % pr, event.detail)
            else:
                print("KeyStr%s" % pr, lookup_keysym(keysym))

            if event.type == X.KeyPress and keysym == XK.XK_Escape:
                local_dpy.record_disable_context(ctx)
                local_dpy.flush()
                return
        elif event.type == X.ButtonPress:
            print("ButtonPress", event.detail)
        elif event.type == X.ButtonRelease:
            print("ButtonRelease", event.detail)
        elif event.type == X.MotionNotify:
            print("MotionNotify", event.root_x, event.root_y)


# Check if the extension is present
if not record_dpy.has_extension("RECORD"):
    print("RECORD extension not found")
    sys.exit(1)
r = record_dpy.record_get_version(0, 0)
print("RECORD extension version %d.%d" % (r.major_version, r.minor_version))

# Create a recording context; we only want key and mouse events
ctx = record_dpy.record_create_context(
    0,
    [record.AllClients],
    [{
        'core_requests': (0, 0),
        'core_replies': (0, 0),
        'ext_requests': (0, 0, 0, 0),
        'ext_replies': (0, 0, 0, 0),
        'delivered_events': (0, 0),
        'device_events': (X.KeyPress, X.MotionNotify),
        'errors': (0, 0),
        'client_started': False,
        'client_died': False,
    }])

# Enable the context; this only returns after a call to record_disable_context,
# while calling the callback function in the meantime
record_dpy.record_enable_context(ctx, record_callback)

# Finally free the context
record_dpy.record_free_context(ctx)
...