.\" Automatically generated by Pod::Man 4.10 (Pod::Simple 3.35) .\" .\" Standard preamble: .\" ======================================================================== .de Sp \" Vertical space (when we can't use .PP) .if t .sp .5v .if n .sp .. .de Vb \" Begin verbatim text .ft CW .nf .ne \\$1 .. .de Ve \" End verbatim text .ft R .fi .. .\" Set up some character translations and predefined strings. \*(-- will .\" give an unbreakable dash, \*(PI will give pi, \*(L" will give a left .\" double quote, and \*(R" will give a right double quote. \*(C+ will .\" give a nicer C++. Capital omega is used to do unbreakable dashes and .\" therefore won't be available. \*(C` and \*(C' expand to `' in nroff, .\" nothing in troff, for use with C<>. .tr \(*W- .ds C+ C\v'-.1v'\h'-1p'\s-2+\h'-1p'+\s0\v'.1v'\h'-1p' .ie n \{\ . ds -- \(*W- . ds PI pi . if (\n(.H=4u)&(1m=24u) .ds -- \(*W\h'-12u'\(*W\h'-12u'-\" diablo 10 pitch . if (\n(.H=4u)&(1m=20u) .ds -- \(*W\h'-12u'\(*W\h'-8u'-\" diablo 12 pitch . ds L" "" . ds R" "" . ds C` "" . ds C' "" 'br\} .el\{\ . ds -- \|\(em\| . ds PI \(*p . ds L" `` . ds R" '' . ds C` . ds C' 'br\} .\" .\" Escape single quotes in literal strings from groff's Unicode transform. .ie \n(.g .ds Aq \(aq .el .ds Aq ' .\" .\" If the F register is >0, we'll generate index entries on stderr for .\" titles (.TH), headers (.SH), subsections (.SS), items (.Ip), and index .\" entries marked with X<> in POD. Of course, you'll have to process the .\" output yourself in some meaningful fashion. .\" .\" Avoid warning from groff about undefined register 'F'. .de IX .. .nr rF 0 .if \n(.g .if rF .nr rF 1 .if (\n(rF:(\n(.g==0)) \{\ . if \nF \{\ . de IX . tm Index:\\$1\t\\n%\t"\\$2" .. . if !\nF==2 \{\ . nr % 0 . nr F 2 . \} . \} .\} .rr rF .\" ======================================================================== .\" .IX Title "X11::Protocol::Ext::XTEST 3pm" .TH X11::Protocol::Ext::XTEST 3pm "2019-08-26" "perl v5.28.1" "User Contributed Perl Documentation" .\" For nroff, turn off justification. Always turn off hyphenation; it makes .\" way too many mistakes in technical documents. .if n .ad l .nh .SH "NAME" X11::Protocol::Ext::XTEST \- synthetic user input and more .SH "SYNOPSIS" .IX Header "SYNOPSIS" .Vb 4 \& use X11::Protocol; \& my $X = X11::Protocol\->new; \& $X\->init_extension(\*(AqXTEST\*(Aq) \& or print "XTEST extension not available"; \& \& $X\->XTestFakeInput (name => \*(AqButtonPress\*(Aq, \& detail => 3); # physical button 3 \& $X\->XTestFakeInput (name => \*(AqButtonRelease\*(Aq, \& detail => 3); .Ve .SH "DESCRIPTION" .IX Header "DESCRIPTION" The \s-1XTEST\s0 extension provides .IP "\(bu" 4 Synthetic keyboard and mouse pointer actions. .IP "\(bu" 4 Displayed cursor comparisons. .IP "\(bu" 4 Test programs continuing during \f(CW\*(C`GrabServer\*(C'\fR by other clients. .PP These things help exercise library or server features which would otherwise require user interaction. .SH "REQUESTS" .IX Header "REQUESTS" The following requests are made available with an \f(CW\*(C`init_extension()\*(C'\fR, as per \*(L"\s-1EXTENSIONS\*(R"\s0 in X11::Protocol. .PP .Vb 1 \& my $is_available = $X\->init_extension(\*(AqXTEST\*(Aq); .Ve .ie n .IP """($server_major, $server_minor) = $X\->XTestGetVersion ($client_major, $client_minor)""" 4 .el .IP "\f(CW($server_major, $server_minor) = $X\->XTestGetVersion ($client_major, $client_minor)\fR" 4 .IX Item "($server_major, $server_minor) = $X->XTestGetVersion ($client_major, $client_minor)" Negotiate a protocol version with the server. \f(CW$client_major\fR and \&\f(CW$client_minor\fR is what the client would like. The returned \&\f(CW$server_major\fR and \f(CW$server_minor\fR is what the server will do. .Sp The current code supports up to 2.1. The intention would be to automatically negotiate in \f(CW\*(C`init_extension()\*(C'\fR if/when necessary. .SS "Cursor Comparisons" .IX Subsection "Cursor Comparisons" .ie n .IP """$is_same = $X\->XTestCompareCursor ($window, $cursor)""" 4 .el .IP "\f(CW$is_same = $X\->XTestCompareCursor ($window, $cursor)\fR" 4 .IX Item "$is_same = $X->XTestCompareCursor ($window, $cursor)" Return true if the cursor attribute of \f(CW$window\fR is equal to \f(CW$cursor\fR. \&\f(CW$cursor\fR can be .RS 4 .IP "\(bu" 4 \&\s-1XID\s0 (an integer) of a cursor. .IP "\(bu" 4 \&\*(L"None\*(R" (or 0). .IP "\(bu" 4 \&\*(L"CurrentCursor\*(R" (or 1) for the currently displayed cursor. .RE .RS 4 .Sp This can be used to check that the cursor attribute of some \f(CW$window\fR is a desired setting, for example .Sp .Vb 2 \& $desired_cursor = $X\->new_rsrc; \& $X\->CreateGlyphCursor ($desired_cursor, ...); \& \& $X\->XTestCompareCursor ($window, $desired_cursor) \& or die "Oops, $window doesn\*(Aqt have desired cursor"; .Ve .Sp Or alternatively, construct a window with a particular cursor and use \&\*(L"CurrentCursor\*(R" to check that what's currently displayed is as desired, for example to see if a \f(CW\*(C`GrabPointer()\*(C'\fR is displaying what's intended, .Sp .Vb 3 \& my $test_window = $X\->new_rsrc; \& $X\->CreateWindow ($test_window, ..., \& cursor => $desired_cursor); \& \& $X\->XTestCompareCursor ($test_window, "CurrentCursor"); \& or die "Oops, currently displayed cursor is not as desired"; .Ve .RE .SS "Simulated Input" .IX Subsection "Simulated Input" .ie n .IP """$X\->XTestFakeInput (name=>...)""" 4 .el .IP "\f(CW$X\->XTestFakeInput (name=>...)\fR" 4 .IX Item "$X->XTestFakeInput (name=>...)" .PD 0 .ie n .IP """$X\->XTestFakeInput ([ name=>... ])""" 4 .el .IP "\f(CW$X\->XTestFakeInput ([ name=>... ])\fR" 4 .IX Item "$X->XTestFakeInput ([ name=>... ])" .ie n .IP """$X\->XTestFakeInput ([ name=>], [name=>], ...)""" 4 .el .IP "\f(CW$X\->XTestFakeInput ([ name=>], [name=>], ...)\fR" 4 .IX Item "$X->XTestFakeInput ([ name=>], [name=>], ...)" .PD Simulate user input for button presses, key presses, and pointer movement. .Sp An input action is specified as an event packet using fields similar to \&\f(CW\*(C`$X\->pack_event()\*(C'\fR. .Sp \&\f(CW\*(C`XTestFakeInput()\*(C'\fR is always a single user action, so for example a button press and button release are two separate \f(CW\*(C`XTestFakeInput()\*(C'\fR requests. For the core events a single event packet is enough to describe an input but some extensions such as \f(CW\*(C`XInputExtension\*(C'\fR may require more. .RS 4 .IP "Button Press and Release" 4 .IX Item "Button Press and Release" The argument fields are .Sp .Vb 3 \& name "ButtonPress" or "ButtonRelease" \& detail physical button number (1 upwards) \& time milliseconds delay before event, default 0 .Ve .Sp For example to fake a physical button 3 press .Sp .Vb 2 \& $X\->XTestFakeInput (name => \*(AqButtonPress\*(Aq, \& detail => 3); .Ve .Sp \&\f(CW\*(C`detail\*(C'\fR is the physical button number, before the core protocol \&\f(CW\*(C`SetPointerMapping()\*(C'\fR translation is applied. To simulate a logical button it's necessary to check \f(CW\*(C`GetPointerMapping()\*(C'\fR to see which physical button, if any, corresponds. .Sp Be careful when faking a \f(CW\*(C`ButtonPress\*(C'\fR as it might be important to fake a matching \f(CW\*(C`ButtonRelease\*(C'\fR too. On the X.org server circa 1.9.x after a synthetic press the physical mouse doesn't work to generate a release and the button is left hung (presumably in its normal implicit pointer grab). .IP "Key Press and Release" 4 .IX Item "Key Press and Release" The argument fields are .Sp .Vb 3 \& name "KeyPress" or "KeyRelease" \& detail keycode (integer) \& time milliseconds delay before event, default 0 .Ve .IP "Mouse Pointer Movement" 4 .IX Item "Mouse Pointer Movement" Mouse pointer motion can be induced with the following. The effect is similar to a \f(CW\*(C`WarpPointer()\*(C'\fR. .Sp .Vb 6 \& name "MotionNotify" \& root XID of root window, default "None" for current \& root_x \e pointer position to move to \& root_y / \& detail flag 0=absolute, 1=relative, default 0 \& time milliseconds delay before event, default 0 .Ve .Sp \&\f(CW\*(C`root\*(C'\fR is the root window (integer \s-1XID\s0) to move on. The default \*(L"None\*(R" (or 0) means the screen the pointer is currently on. .Sp .Vb 3 \& $X\->XTestFakeInput (name => \*(AqMotionNotify\*(Aq, \& root_x => 123, \& root_y => 456); .Ve .Sp \&\f(CW\*(C`detail\*(C'\fR can be 1 to move relative to the current mouse position. .Sp .Vb 4 \& $X\->XTestFakeInput (name => \*(AqMotionNotify\*(Aq, \& root_x => 10, \& root_y => \-20, \& detail => 1); # relative motion .Ve .IP "Other Events" 4 .IX Item "Other Events" Extension events can be faked after an \f(CW\*(C`init_extension()\*(C'\fR so they're recognised by \f(CW\*(C`$X\->pack_event()\*(C'\fR. It's up to the server or extension which events can actually be simulated. .Sp If an extension input requires more than one event packet to describe then pass multiple arrayrefs. For example \f(CW\*(C`DeviceMotion\*(C'\fR (from \&\f(CW\*(C`XInputExtension\*(C'\fR) may need further \f(CW\*(C`DeviceValuator\*(C'\fR packets, .Sp .Vb 3 \& $X\->XTestFakeInput ([ name => \*(AqDeviceMotion\*(Aq, ... ], \& [ name => \*(AqDeviceValuator\*(Aq, ... ], \& [ name => \*(AqDeviceValuator\*(Aq, ... ]); .Ve .RE .RS 4 .Sp For all events \f(CW\*(C`time\*(C'\fR is how long in milliseconds the server should wait before playing the event. The default is 0 for no delay. No further requests are processed from the current client during the delay, so a sequence of \f(CW\*(C`XTestFakeInput()\*(C'\fR with delays will execute sequentially with one delay after another. .Sp Generally the event fields from a \f(CW\*(C`$X\->{\*(Aqevent_handler\*(Aq}\*(C'\fR function cannot be passed directly to \f(CW\*(C`XTestFakeInput()\*(C'\fR to replay it. In particular, .IP "\(bu" 4 \&\f(CW\*(C`time\*(C'\fR from an event is a timestamp, so would have to be zeroed or adjusted to a relative time for a delay in \f(CW\*(C`XTestFakeInput()\*(C'\fR. .IP "\(bu" 4 For \f(CW\*(C`MotionNotify\*(C'\fR, \f(CW\*(C`detail\*(C'\fR from an event is the hint mechanism, so would have to be zeroed for the absolute/relative flag in \f(CW\*(C`XTestFakeInput()\*(C'\fR. .IP "\(bu" 4 For \f(CW\*(C`ButtonPress\*(C'\fR and \f(CW\*(C`ButtonRelease\*(C'\fR, \f(CW\*(C`detail\*(C'\fR from an event is a logical button number after \f(CW\*(C`SetPointerMapping()\*(C'\fR transformation, whereas \&\f(CW\*(C`XFakeInput()\*(C'\fR takes a physical number. A reverse lookup through the \&\f(CW\*(C`GetPointerMapping()\*(C'\fR table would be needed. .RE .RS 4 .RE .SS "GrabServer Imperviousness" .IX Subsection "GrabServer Imperviousness" .ie n .IP """$X\->XTestGrabControl ($impervious)""" 4 .el .IP "\f(CW$X\->XTestGrabControl ($impervious)\fR" 4 .IX Item "$X->XTestGrabControl ($impervious)" Control the current client's behaviour during a \f(CW\*(C`GrabServer()\*(C'\fR by another client. .Sp If \f(CW$impervious\fR is 1 then the current client can continue to make requests, ie. it's impervious to server grabs by other clients. .Sp If \f(CW$impervious\fR is 0 then the current client behaves as normal. Its requests wait during any \f(CW\*(C`GrabServer()\*(C'\fR by another client. .SH "SEE ALSO" .IX Header "SEE ALSO" X11::Protocol, X11::Protocol::Ext::XInputExtension .PP \&\fBxdotool\fR\|(1), X11::GUITest, Xlib \fBXTestQueryExtension\fR\|(3) .PP \&\fI/usr/share/doc/x11proto\-xext\-dev/xtest.txt.gz\fR, \&\fI/usr/share/X11/doc/hardcopy/Xext/xtest.PS.gz\fR .SH "HOME PAGE" .IX Header "HOME PAGE" .SH "LICENSE" .IX Header "LICENSE" Copyright 2011, 2012, 2013, 2014, 2017 Kevin Ryde .PP X11\-Protocol\-Other is free software; you can redistribute it and/or modify it under the terms of the \s-1GNU\s0 General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. .PP X11\-Protocol\-Other is distributed in the hope that it will be useful, but \&\s-1WITHOUT ANY WARRANTY\s0; without even the implied warranty of \s-1MERCHANTABILITY\s0 or \s-1FITNESS FOR A PARTICULAR PURPOSE.\s0 See the \s-1GNU\s0 General Public License for more details. .PP You should have received a copy of the \s-1GNU\s0 General Public License along with X11\-Protocol\-Other. If not, see .