как скрыть курсор в XCB?

Я хочу скрыть системный курсор в Xorg

Я использую xcb для написания X11-приложения для Xorg, в некоторых случаях он будет скрывать курсор (например, xbanish или unclutter). Я пробовал использовать Xfixes: он отлично работает с xlib, но не работает с xcb.

Мой код для xlib, который скрывает курсор:

#include <X11/Xlib.h>
#include <X11/extensions/Xfixes.h>

Display *conn = XOpenDisplay(NULL);
XFixesHideCursor(conn, DefaultRootWindow(conn));
Xflush(conn);

Мой код для xcb, который ничего не делает:

#include <xcb/xcb.h>
#include <xcb/xfixes.h>

xcb_connection_t *conn = xcb_connect(NULL, NULL);
xcb_screen_t *screen = xcb_setup_roots_iterator(xcb_get_setup(conn)).data;
xcb_xfixes_hide_cursor(conn, screen->root);
xcb_flush(conn);

Я хочу понять, почему код для xcb ничего не делает или просто скрывает курсор в xcb.

UPD

xtrace мне ничего не дал, ошибок не видит. Но я уверен, что в xcb_xfixes_hide_cursor есть ошибка, потому что этот код дает мне не-NULL generic_error:

xcb_void_cookie_t cookie = xcb_xfixes_hide_cursor_checked(conn, screen->root);
xcb_generic_error_t *generic_error = xcb_request_check(conn, cookie);

На самом деле, это дает мне эту ошибку:

{
  "error_code": 1,
  "major_code": 138,
  "minor_code": 29,
  "sequence:": 2,
  "full_sequence": 2
}

Я использую xcb_errors_get_name_for_minor_code и xcb_errors_get_name_for_major_code из xcb-util-errors, чтобы узнать что-нибудь об ошибке. Это возникает внутри xcb_xfixes_hide_cursor_checked.


person Uladzislau_Khamkou    schedule 08.09.2019    source источник
comment
Что показывает x11trace с версией xcb?   -  person Sam Varshavchik    schedule 08.09.2019


Ответы (2)


На самом деле, это дает мне эту ошибку:

{ "error_code": 1, "major_code": 138, "minor_code": 29, "sequence:": 2, "full_sequence": 2 }

Ошибка 1: BadRequest/XCB_REQUEST. Вы получаете ошибку BadRequest, потому что вы не инициализировали расширение XFIXES (= проинформировали сервер X11 о вашей поддерживаемой версии).

Соответствующий код на сервере, который проверяет, действителен ли запрос для версии, предоставленной клиентом: https://codesearch.debian.net/show?file=xorg-server_2%3A1.20.4-1%2Fxfixes%2Fxfixes.c&line=150#L150< /а>

Из спецификации протокола (https://codesearch.debian.net/show?file=xorg-server_2%3A1.20.4-1%2Fxfixes%2Fxfixes.c&line=150#L150):

4. Extension initialization

The client must negotiate the version of the extension before executing
extension requests.  Behavior of the server is undefined otherwise.

QueryVersion
[...]

Таким образом, чтобы ответить на ваш вопрос: вам нужно выполнить xcb_xfixes_query_version(c, 4, 0), прежде чем вы сможете выполнять HideCursor запросов.

Чтобы ответить на ваш первый дополнительный вопрос: версия 4.0 — это версия, которая представила HideCursor. Это можно увидеть в спецификации протокола, поскольку HideCursor задокументирован в разделе "XFIXES VERSION 4 ИЛИ BETTER".

Чтобы ответить на ваш второй дополнительный вопрос: XFixesHideCursor автоматически запрашивает версию для вас: https://codesearch.debian.net/show?file=libxfixes_1%3A5.0.3-1%2Fsrc%2FCursor.c&line=255#L250

Этот код завершается вызовом XFixesHideCursor -> XFixesFindDisplay -> XFixesExtAddDisplay, и эта функция запрашивает версию: https://codesearch.debian.net/show?file=libxfixes_1%3A5.0.3-1%2Fsrc%2FXfixes.c&line=79#L79

person Uli Schlachter    schedule 10.09.2019

Вообще говоря, самый простой способ скрыть курсор — заменить его пустым курсором.

xcb_void_cookie_t
xcb_create_glyph_cursor (xcb_connection_t *connection,
                         xcb_cursor_t      cursorId,
                         xcb_font_t        source_font, /* font for the source glyph */
                         xcb_font_t        mask_font,   /* font for the mask glyph or XCB_NONE */
                         uint16_t          source_char, /* character glyph for the source */
                         uint16_t          mask_char,   /* character glyph for the mask */
                         uint16_t          fore_red,    /* red value for the foreground of the source */
                         uint16_t          fore_green,  /* green value for the foreground of the source */
                         uint16_t          fore_blue,   /* blue value for the foreground of the source */
                         uint16_t          back_red,    /* red value for the background of the source */
                         uint16_t          back_green,  /* green value for the background of the source */
                         uint16_t          back_blue ); /* blue value for the background of the source */

Мы должны иметь возможность передать ' ' для source_char и mask_char. Однако для этого нам нужно передать обычный шрифт, а не шрифт курсора.

Я обнаружил, что старая идея показывать и скрывать курсоры несколько проблематична. Насколько я могу судить, API несколько чувствителен к современным оконным менеджерам.

person Joshua    schedule 08.09.2019