LinuxQuestions.org
Welcome to the most active Linux Forum on the web.
Home Forums Tutorials Articles Register
Go Back   LinuxQuestions.org > Forums > Linux Forums > Linux - Desktop
User Name
Password
Linux - Desktop This forum is for the discussion of all Linux Software used in a desktop context.

Notices


Reply
  Search this Thread
Old 04-11-2018, 07:00 PM   #1
Franek11
LQ Newbie
 
Registered: Apr 2018
Posts: 4

Rep: Reputation: Disabled
XSendEvent doesn't work with inactive window


Hi,
I've got a code that send event that 'A' key is was pressed to window:

0. Sleep(5)
1. XGetInputFocus
2. Sleep(5)
3. XSendEvent


The problem is that if I change the active window of a window during step 2, then the function will have no effect. If the window has not changed, the key will be pressed successfully.

What causes this behavior? Is it easy to get around this (including, for example, a simple change and recompilation of the xorg server)? Is there a better way to send an input keyboard/mouse event?


Code:
PHP Code:
// Send a fake keystroke event to an X window.
// by Adam Pierce - http://www.doctort.org/adam/
// This is public domain software. It is free to use by anyone for any purpose.

#include <X11/Xlib.h>
#include <X11/keysym.h>
#include <iostream>
#include <unistd.h>
using namespace std;
// The key code to be sent.
// A full list of available codes can be found in /usr/include/X11/keysymdef.h
#define KEYCODE XK_A

// Function to create a keyboard event
XKeyEvent createKeyEvent(Display *displayWindow &win,
                           
Window &winRootbool press,
                           
int keycodeint modifiers)
{
   
XKeyEvent event;

   
event.display     display;
   
event.window      win;
   
event.root        winRoot;
   
event.subwindow   None;
   
event.time        CurrentTime;
   
event.x           1;
   
event.y           1;
   
event.x_root      1;
   
event.y_root      1;
   
event.same_screen True;
   
event.keycode     XKeysymToKeycode(displaykeycode);
   
event.state       modifiers;

   
cout<<display<<" "<<win<<" "<<winRoot<<" "<<event.keycode<<endl;

   if(
press)
      
event.type KeyPress;
   else
      
event.type KeyRelease;

   return 
event;
}


char *getWindowName(Display *dispWindow win) {
    
Atom prop XInternAtom(disp,"WM_NAME",False), type;
    
int form;
    
unsigned long remainlen;
    
unsigned char *list;


    if (
XGetWindowProperty(disp,win,prop,0,1024,False,AnyPropertyType,
                &
type,&form,&len,&remain,&list) != Success) { // XA_STRING

        
return NULL;
    }

    return (
char*)list;
}


main()
{
sleep(5);
// Obtain the X11 display.
   
Display *display XOpenDisplay(0);
   if(
display == NULL)
      return -
1;

// Get the root window for the current display.
   
Window winRoot XDefaultRootWindow(display);

// Find the window which has the current keyboard focus.
   
Window winFocus;
   
int    revert;
   
XGetInputFocus(display, &winFocus, &revert);
   
cout<<"Get"<<endl;
   
sleep(5);
// Send a fake key press event to the window.
   
XKeyEvent event createKeyEvent(displaywinFocuswinRoottrueKEYCODE0);
   
cout << XSendEvent(event.displayevent.windowTrueKeyPressMask, (XEvent *)&event) << endl;

// Send a fake key release event to the window.
   
event createKeyEvent(displaywinFocuswinRootfalseKEYCODE0);
   
cout << XSendEvent(event.displayevent.windowTrueKeyPressMask, (XEvent *)&event) <<endl;
   
cout << getWindowName(display,winFocus);
// Done.
   
XFlush(display);
   
XCloseDisplay(display);
   return 
0;

 
Old 04-11-2018, 07:23 PM   #2
Keith Hedger
Senior Member
 
Registered: Jun 2010
Location: Wiltshire, UK
Distribution: Void, Linux From Scratch, Slackware64
Posts: 3,154

Rep: Reputation: 857Reputation: 857Reputation: 857Reputation: 857Reputation: 857Reputation: 857Reputation: 857
You need to use xsetinputfocus just before sending the key there is also xgrabkeyboard and xgrabpointer see the xlib docs such as they are.
 
Old 04-12-2018, 07:16 PM   #3
Franek11
LQ Newbie
 
Registered: Apr 2018
Posts: 4

Original Poster
Rep: Reputation: Disabled
Is any method (maybe other function or something) to do it in the background (as user or as root)?
 
Old 04-13-2018, 05:41 AM   #4
Keith Hedger
Senior Member
 
Registered: Jun 2010
Location: Wiltshire, UK
Distribution: Void, Linux From Scratch, Slackware64
Posts: 3,154

Rep: Reputation: 857Reputation: 857Reputation: 857Reputation: 857Reputation: 857Reputation: 857Reputation: 857
Quote:
Originally Posted by Franek11 View Post
Is any method (maybe other function or something) to do it in the background (as user or as root)?
This is nonsensical, it doesn't matter what user you are using as long as they can communicate with the X server, the code you show is C++ and needs compiling etc, if you need to do this from the command line please make that clear and there are plenty of tools to do this just search.
 
Old 04-14-2018, 10:14 AM   #5
Franek11
LQ Newbie
 
Registered: Apr 2018
Posts: 4

Original Poster
Rep: Reputation: Disabled
I mean, I'd like to control two programs at once. One by me using the keyboard (live), the other in the background controlled by the program. Changing the window with the active focus causes the keyboard events to go to another window.

My guess is that it could be security or xorg server property. Therefore, there is no problem if I had to make some minor modifications to the settings or code. Unless it will require a large amount of work.

I can also use another method.

Last edited by Franek11; 04-14-2018 at 10:29 AM.
 
Old 04-17-2018, 09:53 PM   #6
AwesomeMachine
LQ Guru
 
Registered: Jan 2005
Location: USA and Italy
Distribution: Debian testing/sid; OpenSuSE; Fedora; Mint
Posts: 5,524

Rep: Reputation: 1015Reputation: 1015Reputation: 1015Reputation: 1015Reputation: 1015Reputation: 1015Reputation: 1015Reputation: 1015
The whole point of window focus is that the keyboard attaches to it. Otherwise, how does the keyboard know where to be active?
 
Old 04-20-2018, 05:23 PM   #7
Franek11
LQ Newbie
 
Registered: Apr 2018
Posts: 4

Original Poster
Rep: Reputation: Disabled
Yes, I understand it. But...

As I wroted all I need is to control two or more program at once. To achieve this I want to use the program like this one written above. The problem is that the function used there does not work when the focus is not connected to the window.

I would like to achieve that goal is accomplished two tasks simultaneously:
1. The ability to continuously click and write, e.g. in a web browser or other programs using the keyboard.
2. A program written, compiled and running will control other windows (one, two or more) simultaneously.

I used the xsetinputfocus function, but unfortunately it requires moments of time between the change of focus (maybe milliseconds or more depending on the load). If it is possible, I would prefer to do it in a more universal way, without tricks such as replacing the focus by pressing the key and returning the focus to the previous window.


Quote:
Originally Posted by AwesomeMachine View Post
The whole point of window focus is that the keyboard attaches to it. Otherwise, how does the keyboard know where to be active?
XSendEvent gets a desktop and window id, but the event doesn't take effect if the window doesn't has a focus.

Last edited by Franek11; 04-20-2018 at 05:28 PM.
 
Old 04-20-2018, 05:41 PM   #8
BW-userx
LQ Guru
 
Registered: Sep 2013
Location: Somewhere in my head.
Distribution: Slackware (15 current), Slack15, Ubuntu studio, MX Linux, FreeBSD 13.1, WIn10
Posts: 10,342

Rep: Reputation: 2242Reputation: 2242Reputation: 2242Reputation: 2242Reputation: 2242Reputation: 2242Reputation: 2242Reputation: 2242Reputation: 2242Reputation: 2242Reputation: 2242
you're logic is off
Code:
0. Sleep(5)
1. XGetInputFocus
2. Sleep(5)
3. XSendEvent
should be something like this:
Code:
0. Sleep(5)
1. XGetInputFocus
2. XSendEvent
3. Sleep(5)
Have you ever tried to get someone to do something for you while they're sleeping? You have to wake them up to get their attention to focus on something.


A program written, compiled and running will control other windows (one, two or more) simultaneously.

simultaneously: that is just an ideal world, CPU takes instructions and processes them one at a time, a queue is involved in this endeavor.

threading:

Multi-Processers:

Hyper-threading:

capturing the the child's process ID
two children, who are their parents?

get PID from each child, put them in the back ground, then schedule them to do whatever whenever.

that is just theoretical programming ideas, or spit balling. but its something.

Last edited by BW-userx; 04-20-2018 at 05:49 PM.
 
Old 05-23-2018, 05:29 PM   #9
andreyssop
LQ Newbie
 
Registered: May 2018
Location: Россия
Distribution: andreyssopWU
Posts: 8

Rep: Reputation: 0
XSendEvent doesnt work with inactive window

If i play games in windowed mode, It doesnt allow me to change the gamma in game; however, I can change the gamma in the catalyst control center. Have you tried that?
 
  


Reply



Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is Off
HTML code is Off



Similar Threads
Thread Thread Starter Forum Replies Last Post
Desktop -> Administration -> Login Window doesn't work cccc Debian 3 11-30-2007 05:28 AM
Window Manager doesn't work after Feisty Upgrade trevor4706 Ubuntu 1 04-22-2007 06:03 PM
Sound Card Shows up in Detection Window....but Testsound doesn't work shimano55 Linux - Hardware 1 03-22-2005 05:36 PM
Mouse doesn't work in terminal window. djKale Linux - Newbie 2 02-01-2005 09:38 AM
ALT doesn't work in some window managers ivanatora Linux - Software 1 10-27-2004 08:42 AM

LinuxQuestions.org > Forums > Linux Forums > Linux - Desktop

All times are GMT -5. The time now is 09:24 PM.

Main Menu
Advertisement
My LQ
Write for LQ
LinuxQuestions.org is looking for people interested in writing Editorials, Articles, Reviews, and more. If you'd like to contribute content, let us know.
Main Menu
Syndicate
RSS1  Latest Threads
RSS1  LQ News
Twitter: @linuxquestions
Open Source Consulting | Domain Registration