LinuxQuestions.org
Welcome to the most active Linux Forum on the web.
Home Forums Tutorials Articles Register
Go Back   LinuxQuestions.org > Forums > Non-*NIX Forums > Programming
User Name
Password
Programming This forum is for all programming questions.
The question does not have to be directly related to Linux and any language is fair game.

Notices


Reply
  Search this Thread
Old 01-04-2012, 06:20 PM   #1
hydraMax
Member
 
Registered: Jul 2010
Location: Skynet
Distribution: Debian + Emacs
Posts: 467
Blog Entries: 60

Rep: Reputation: 51
Learning Xlib: Get next Button Press on the display


For learning purposes, I was hoping to write a small C program that would wait for the next Button Press anywhere on the display. After reading through a bunch of the Xlib documentation, I thought this would work:

Code:
#include <X11/Xlib.h>
#include <stdlib.h>
#include <stdio.h>

int main() {
  Display * dpy = XOpenDisplay(NULL);
  if(dpy == NULL) {
    fprintf(stderr, "error: could not open display.");
    exit(EXIT_FAILURE);
  }
  Window rootw = XDefaultRootWindow(dpy);
  XSelectInput(dpy, rootw, ButtonPressMask);
  XEvent * e;
  XNextEvent(dpy, e);
  /*
    Display some information about the event probably...
   */
}
But that always dies with:

Code:
X Error of failed request:  BadAccess (attempt to access private resource denied)
  Major opcode of failed request:  2 (X_ChangeWindowAttributes)
  Serial number of failed request:  7
  Current serial number in output stream:  7
Edit: I think the problem above is that I am not grabbing the pointer first. This seems to work:

Code:
#include <X11/Xlib.h>
#include <stdlib.h>
#include <stdio.h>
#include <X11/cursorfont.h>

int main() {
  Display * dpy = XOpenDisplay(NULL);
  if(dpy == NULL) {
    fprintf(stderr, "error: could not open display.");
    exit(EXIT_FAILURE);
  }
  Cursor csr = XCreateFontCursor(dpy, XC_crosshair);
  switch(csr) {
  case BadAlloc:
    fprintf(stderr, "error: BadAlloc during XCreateFontCursor");
    exit(EXIT_FAILURE);
  case BadValue:
    fprintf(stderr, "error: BadValue during XCreateFontCursor");
    exit(EXIT_FAILURE);
  }
  Window rootw = XDefaultRootWindow(dpy);
  XEvent evt;
  int err = XGrabPointer(dpy,
  			 rootw,
  			 False,
  			 ButtonPressMask,
  			 GrabModeAsync,
  			 GrabModeAsync,
  			 None,
  			 csr,
  			 CurrentTime);
  switch(err) {
  case BadCursor:
    fprintf(stderr, "error: BadCursor during XGrabPointer");
    exit(EXIT_FAILURE);
  case BadValue:
    fprintf(stderr, "error: BadCursor during XGrabPointer");
    exit(EXIT_FAILURE);
  case BadWindow:
    fprintf(stderr, "error: BadCursor during XGrabPointer");
    exit(EXIT_FAILURE);
  }
  XNextEvent(dpy, &evt);
  printf("got it!\n");
  /*
    Display some information about the event probably...
   */
}
Is there anything technically wrong with this approach?

Last edited by hydraMax; 01-05-2012 at 02:01 PM. Reason: possible solution
 
Old 01-09-2012, 05:14 PM   #2
kalleanka
Member
 
Registered: Aug 2003
Location: Mallorca, Spain
Distribution: xubuntu
Posts: 551

Rep: Reputation: 38
I think your window is not done and some event happens. Use XSync() before event loop. X is really messy.


Try something like...

....

XSync(dpy, 0); // to avoid chase

while(XPending(dpy))
{
XNextEvent(dpy, &evt);
printf("got it!\n");
/*
Display some information about the event probably...
*/
}

....

Last edited by kalleanka; 01-09-2012 at 05:17 PM.
 
Old 01-10-2012, 03:19 AM   #3
hydraMax
Member
 
Registered: Jul 2010
Location: Skynet
Distribution: Debian + Emacs
Posts: 467

Original Poster
Blog Entries: 60

Rep: Reputation: 51
@kalleanka: Thank you for the reply, but I am slightly confused: why do I need an event loop? (I literally only need the first mouse click that occurs after starting the program.)
 
Old 01-10-2012, 10:14 AM   #4
kalleanka
Member
 
Registered: Aug 2003
Location: Mallorca, Spain
Distribution: xubuntu
Posts: 551

Rep: Reputation: 38
well because normally when you set an eventmask like this XSelectInput(dpy, rootw, ButtonPressMask); you get a flow of events and you only catch the first or the one in the buffert. You nead a switch statement to and sometimes some if statements to select you event you are looking for. Your program just runs to the end only catching the first event of a flow. The XPending is not needed but makes the program more efficient as i understand it.


I see now that i missed the event loop. It should be like this.

....

XSync(dpy, 0); // to avoid chase
while(1)
{
while(XPending(dpy))
{
XNextEvent(dpy, &evt);
printf("got it!\n");


switch(evt.type)
{
case ....

case .....


}


/*
Display some information about the event probably...
*/
}
}





If you need timeouts you insert a select in your loop. If you need critical timeout checks or tasks you make an new thread before the main event loop to handle the critical tasks or checks. I do not think X is threadsafe so be aware.

Last edited by kalleanka; 01-10-2012 at 10:16 AM.
 
  


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
Turn the power button into a key press? jsteel Linux - General 2 04-21-2011 01:47 AM
C++/QT3 accept button when press entered... BUT ... DropSig Programming 3 07-31-2008 06:41 AM
disable shutdown by press the power button nickraj General 8 03-02-2007 11:16 PM
I want my Controller to output text with button press timrs Linux - Games 9 01-08-2007 06:19 AM
Press power button can't turn down the computer shadkong Linux - Hardware 2 05-04-2005 09:50 PM

LinuxQuestions.org > Forums > Non-*NIX Forums > Programming

All times are GMT -5. The time now is 03:39 AM.

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