Trying to send a mouse wheel scroll to a specific window. It can be done with the XTest extension xdotool uses:
xdotool click 5
But this doesn't seem to target the specific window and doesn't work with the Xvfb X11 server.
I'm using this test QML application launched with qmlscene:
import QtQuick 2.0
import QtQuick.Controls 2.2
import QtQuick.Window 2.2
import QtQuick.Layouts 1.15
import QtQuick.Controls.Styles 1.4
Window {
width: 800
height: 600
ColumnLayout {
anchors.fill: parent
spacing: 10
Button {
text: "Button"
Layout.alignment: Qt.AlignHCenter
}
SpinBox {
Layout.fillWidth: true
value: 50
width: 200
}
ScrollView {
Layout.fillWidth: true
Layout.fillHeight: true
TextArea {
background: Rectangle {
}
text: "TextArea\nTextArea is a multi-line text editor. TextArea extends TextEdit with a placeholder text functionality, and adds decoration.\nTextArea is not scrollable by itself. Especially on screen-size constrained platforms, it is often preferable to make entire application pages scrollable. On such a scrollable page, a non-scrollable TextArea might behave better than nested scrollable controls. Notice, however, that in such a scenario, the background decoration of the TextArea scrolls together with the rest of the scrollable content.\n...\n...\n...\n...\nTextArea\nTextArea is a multi-line text editor. TextArea extends TextEdit with a placeholder text functionality, and adds decoration.\nTextArea is not scrollable by itself. Especially on screen-size constrained platforms, it is often preferable to make entire application pages scrollable. On such a scrollable page, a non-scrollable TextArea might behave better than nested scrollable controls. Notice, however, that in such a scenario, the background decoration of the TextArea scrolls together with the rest of the scrollable content.\n...\n...\n...\n...\nTextArea\nTextArea is a multi-line text editor. TextArea extends TextEdit with a placeholder text functionality, and adds decoration.\nTextArea is not scrollable by itself. Especially on screen-size constrained platforms, it is often preferable to make entire application pages scrollable. On such a scrollable page, a non-scrollable TextArea might behave better than nested scrollable controls. Notice, however, that in such a scenario, the background decoration of the TextArea scrolls together with the rest of the scrollable content."
}
}
}
}
I've tried XCB with xinput:
#include <assert.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <xcb/xcb.h>
#include <xcb/xinput.h>
int main(int argc, char *argv[])
{
if (argc != 2) {
fprintf(stderr, "Error: one parameter expected: window id\n");
return 1;
}
char *end;
const unsigned long window_id = strtoul(argv[1], &end, 0);
if (end != argv[1] + strlen(argv[1])) {
fprintf(stderr, "Error: failed to parse window id\n");
return 1;
}
xcb_connection_t *xcb_connection = xcb_connect(NULL, NULL);
if (xcb_connection_has_error(xcb_connection)) {
fprintf(stderr, "Error: xcb_connect() failed\n");
return 1;
}
const xcb_setup_t* setup = xcb_get_setup(xcb_connection);
xcb_screen_iterator_t iter = xcb_setup_roots_iterator(setup);
xcb_screen_t* xcb_screen = iter.data;
xcb_window_t root = xcb_screen->root;
const xcb_query_extension_reply_t *reply = xcb_get_extension_data(xcb_connection, &xcb_input_id);
if (!reply || !reply->present) {
fprintf(stderr, "Error: xinput get_extension_data failed\n");
return 1;
}
assert(reply->major_opcode == 131);
xcb_input_motion_event_t event = {0};
event.response_type = XCB_INPUT_MOTION;
event.extension = reply->major_opcode;
event.length = sizeof(event);
event.detail = XCB_BUTTON_INDEX_5;
event.root_x = 300;
event.root_y = 300;
event.event_x = 300;
event.event_y = 300;
xcb_send_event(xcb_connection, 0, window_id, XCB_EVENT_MASK_NO_EVENT, (const char *)&event);
xcb_flush(xcb_connection);
usleep(1000000);
xcb_disconnect(xcb_connection);
return 0;
}
CMakeLists.txt:
cmake_minimum_required(VERSION 3.16)
project(inject-x11 LANGUAGES C)
# Extra CMake Modules to find XCB.
find_package(ECM REQUIRED NO_MODULE)
set(CMAKE_MODULE_PATH ${ECM_FIND_MODULE_DIR})
find_package(XCB REQUIRED XCB XINPUT)
add_executable(${PROJECT_NAME})
target_sources(${PROJECT_NAME} PRIVATE
main.c
)
target_link_libraries(${PROJECT_NAME} PRIVATE
XCB::XINPUT
)
I've looked at the X11 protocol data with Wireshark:
socat tcp-listen:6004,reuseaddr,fork unix:/tmp/.X11-unix/X0
DISPLAY=localhost:4 qmlscene test.qml
When scrolling with the mouse there are some xinput GenericEvent messages are transferred (extension code 131 - the code of xcb_input). I can't replicate them with xcb_input. What's the method for simulating the mouse wheel properly?