Why does XWarpPointer only work once (while in a loop)? - c

Why does XWarpPointer only work once?
When I run:
#include <stdio.h>
#include <X11/Xlib.h>
#include <X11/Xutil.h>
#include <X11/Xatom.h>
int main()
{
Display *dpy = XOpenDisplay(0);
while (1) {
Window root_window;
root_window = XRootWindow(dpy, 0);
XSelectInput(dpy, root_window, KeyReleaseMask);
XWarpPointer(dpy, None, root_window, 0, 0, 0, 0, 100, 100);
XSync(dpy, False);
}
}
The mouse should appear locked in a single position. But it only moves the mouse once and then lets me move it around while the loop is still runnning. What is causing the XWarpPointer to only run once? Is it some kind of X11 feature to protect the user from the application?
FYI, I am running RHEL 5.2 on VMWare Fusion on Mac OSX 10.6.
Update:
When running the binary, components
like a button or icon flicker, but
the visual mouse cursor stays where I
move it.
After the one time XWarpPointer does
work, when I move the mouse, the
cursor jumps to near where it was
before I warped it. It's as if there
is a (last_x,last_y) that is not
getting updated.
When I change the pointer via
OpenVMTools it seems to make the
pointer stick to the desired location
more, but the visual pointer does not
change.
Thanks,
Chenz

I've no experience here but what happens if you don't discard events in XSync? e.g. XSync(dpy, True);?

After
XWarpPointer(dpy, None, root_window, 0, 0, 0, 0, 100, 100);
Try
XFlush(dpy);
This should solve the problem.

Related

Resizing windows in curses

I have several tiled windows in curses, initialized like this
int row, col;
getmaxyx(stdscr, row, col);
WINDOW* a = newwin(row, col/2, 0, 0);
WINDOW* b = newwin(row, col/2, 0, col/2);
box(a, 0, 0);
box(b, 0, 0);
/* Refresh stdscr and windows...
...
*/
If the user resizes the terminal, I would like to resize the windows accordingly, what's the best way to do this? All I can think of is deleting the old windows and making new ones, but that can be kind of tedious when I'm dealing with multiple windows

X11 Why I can't draw any text?

I'm trying to learn X11. It's very hard to me, because I don't have experience with window applications on Linux.
I wrote some simple code and I can't resolve this not visible text problem.
Everything is working good probably, when I was trying to draw rectangle with DrawRectangle function it was working.
Here is the code:
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <X11/Xlib.h>
int main()
{
Display* myDisplay;
Window myWindow;
int myScreen;
GC myGC;
XEvent myEvent;
unsigned long black, white;
char* hello = "Hello world!";
XFontStruct* myFont;
if((myDisplay = XOpenDisplay(NULL)) == NULL)
{
puts("Error in conneting to X Server!");
return -1;
}
myScreen = DefaultScreen(myDisplay);
black = BlackPixel(myDisplay, myScreen);
white = WhitePixel(myDisplay, myScreen);
myWindow = XCreateSimpleWindow(myDisplay, RootWindow(myDisplay, myScreen), 0, 0, 640, 320, 5, black, white);
XSelectInput(myDisplay, myWindow, ExposureMask);
XClearWindow(myDisplay, myWindow);
XMapWindow(myDisplay, myWindow);
myGC = XCreateGC(myDisplay, myWindow, 0, 0);
XSetForeground(myDisplay, myGC, black);
XSetBackground(myDisplay, myGC, white);
myFont = XLoadQueryFont(myDisplay, "-Misc-Fixed-Medium-R-Normal--7-70-75-75-C-50-ISO10646-1");
XSetFont(myDisplay, myGC, myFont->fid);
while(1)
{
XNextEvent(myDisplay, &myEvent);
if(myEvent.type == Expose)
{
XClearWindow(myDisplay, myWindow);
// HERE I DONT KNOW WHY IT DOESNT WORK!
XDrawString(myDisplay, myWindow, myGC, 0, 0, hello, strlen(hello));
}
}
XFreeGC(myDisplay, myGC);
XDestroyWindow(myDisplay, myWindow);
XCloseDisplay(myDisplay);
return 0;
}
Thank you for help!
Your font path argument to XLoadQueryFont is wrong (on my Linux/Debian desktop). Check with the xlsfonts command the right ones (they are all lowercases).
With
myFont = XLoadQueryFont
(myDisplay,
"-misc-fixed-medium-r-normal--9-90-75-75-c-60-iso10646-1");
it could work better. Try also with "lucidasanstypewriter-bold-14"
And most importantly the coordinates passed to XDrawString are wrong. Remember that they are the coordinates of the baseline of your text. And x=0, y=0 is the top left corner of the window, and y is growing downwards and x is growing to the right. Hence your text is drawn off-window, above its top. So y should be positive and more than the font height.
Try
XDrawString (myDisplay, myWindow, myGC, 15, 20, hello,
strlen (hello));
As I commented, you need to handle a lot more events.
I don't have experience with window applications on Linux.
And to learn about GUI programming, I strongly recommend first using some toolkit like GTK or Qt or perhaps SDL.
Raw X11 programming is too hard (and by the time you'll learn it is will be obsolete, e.g. by Wayland), in particular because an X11 application needs to be ICCCM & EWMH compliant. Notice that the entire X11 documentation requires nearly ten thousand pages.
See also https://tronche.com/gui/x/xlib/
BTW, most Linux GUI applications are drawing pixmap client side and sending it to the X11 server. Read about compositing window managers. Drawing requests like XDrawString are no more used anymore in practice. Recent font related libraries like libfontconfig, libXft, etc are working on the client side.

Xlib + Unity Only close allowed action

I just want to make a sample app when the only possible action is close.
Is this possible with Unity(Ubuntu) ?
Do i make a mistake ?
#include <stdio.h>
#include <X11/Xlib.h>
#include <X11/Xos.h>
#include <X11/Xatom.h>
static void only_close(Display *display, Window window)
{
int retval;
Atom aa = XInternAtom(display, "_NET_WM_ALLOWED_ACTIONS", False);
Atom close = XInternAtom(display, " _NET_WM_ACTION_CLOSE", False);
retval = XChangeProperty(display, window, aa, XA_ATOM, 32, PropModeReplace, (unsigned char*)close, 1);
printf("###### XChangeProperty() reted %d\n", retval);
}
int main()
{
Display *dis;
Window win;
dis = XOpenDisplay(NULL);
win = XCreateSimpleWindow(dis, RootWindow(dis, 0), 1, 1, 500, 500, \
0, BlackPixel (dis, 0), BlackPixel(dis, 0));
XMapWindow(dis, win);
printf("window %i\n", (int)win);
only_close(dis, win);
XFlush(dis);
sleep(10);
return(0);
}
First, you need (unsigned char*)&close (an address of the data)
Second, you are setting the property too early, before WM has a chance to manage the window. A WM must discard the old value of this property when it first manages the window. Try after the first expose event, or just after a delay of 1 second.
Third, it is not guaranteed to work. On my machine (not Unity) the window actions in the taskbar are indeed disabled, but the window frame still has them the WM still allows them. I don't know if it's a bug in my WM or not.

Does this SDL_gfx code involve a race condition?

When I run the following code on my machine, it doesn't behave deterministically. The triangle it should draw only appears sometimes:
#include <SDL/SDL.h>
#include <SDL/SDL_gfxPrimitives.h>
int main(int argc, char* args[])
{
int xres = 250;
int yres = 250;
SDL_Surface* screen = SDL_SetVideoMode(xres, yres,
0, SDL_SWSURFACE | SDL_DOUBLEBUF | SDL_NOFRAME);
SDL_FillRect(screen, NULL, SDL_MapRGB(screen->format, 0, 0, 0));
filledTrigonRGBA(screen, 10, 10, 170, 170, 75, 100, 255, 0, 255, 255);
//SDL_Delay(1); // this fixes some race condition?
SDL_Flip(screen);
SDL_Delay(1000);
SDL_Quit();
return 0;
}
But if I uncomment the first SDL_Delay() call, the triangle always appears. I have also observed this when using SDL 2.
Is there a race condition in one of the libraries here, or is something wrong with my computer?
There are many things involved, especially if you have compositing window manager. Like if you flip your resulting image but window wasn't visible at that moment. With compositing it is even worse since it implements its own double buffering.
Just repeatedly draw it a loop, like every single example does. If you absolutely have to, you can redraw only on window events (mostly 'exposed' one).

How to set mouse cursor position in C on linux?

how can I set the mouse cursor position in an X window using a C program under Linux?
thanks :)
(like setcursorpos() in WIN)
EDIT:
I've tried this code, but doesn't work:
#include <curses.h>
main(){
move(100, 100);
refresh();
}
12.4 - Moving the Pointer
Although movement of the pointer
normally should be left to the control
of the end user, sometimes it is
necessary to move the pointer to a new
position under program control.
To move the pointer to an arbitrary
point in a window, use XWarpPointer().
Example:
Display *dpy;
Window root_window;
dpy = XOpenDisplay(0);
root_window = XRootWindow(dpy, 0);
XSelectInput(dpy, root_window, KeyReleaseMask);
XWarpPointer(dpy, None, root_window, 0, 0, 0, 0, 100, 100);
XFlush(dpy); // Flushes the output buffer, therefore updates the cursor's position. Thanks to Achernar.
This is old, but in case someone else comes across this issue. The answer provided by tusbar was correct but the command XFlush(dpy) must be added at the end to update the cursor's position. The libraries needed are: X11/X.h, X11/Xlib.h, X11/Xutil.h.
int main(int argc, char *argv[]){
//Get system window
Display *dpy;
Window root_window;
dpy = XOpenDisplay(0);
root_window = XRootWindow(dpy, 0);
XSelectInput(dpy, root_window, KeyReleaseMask);
XWarpPointer(dpy, None, root_window, 0, 0, 0, 0, 100, 100);
XFlush(dpy);
return 0;}
PS: You can use this command to build the code gcc main.c -lX11
You want to write a X11 program that uses the call XWarpPointer function to move the point to a relative or global position. (Xlib Programming Manual, Vol 1)
In general, using Xlib for programming the X Window System, is the most basic, and quite low-level interface for graphical programming on a Unix or Linux system. Most applications developed nowadays using a higher level library such as GTK or Qt for developing their GUI applications.
Curses or NCurses (New Curses) is for programming terminal-oriented interfaces, so are not useful in this case.
use Jordan Sissel's excellent utility xdotool.
http://www.semicomplete.com/projects/xdotool/
it provide XWarpPointer wrapper function like xdo_mousemove(), here is some example:
Display *display = NULL;
xdo_t *xdo = NULL;
void mouse_left_down(int x, int y)
{
xdo_mousemove(xdo, x, y, 0)
xdo_mousedown(xdo, CURRENTWINDOW, Button1);
}
void mouse_left_up(int x, int y)
{
xdo_mouseup(xdo, CURRENTWINDOW, Button1, 1, 0);
}
void mouse_left_double_click(int x, int y)
{
xdo_mousemove(xdo, x, y, 0);
xdo_click_multiple(xdo, CURRENTWINDOW, Button1, 1, 0);
doubleclick = TRUE;
}
int main()
{
display = XOpenDisplay(NULL);
if(display == NULL)
{
fprintf(stderr, "can't open display!\n");
return -1;
}
xdo = xdo_new((char*) display);
//some task here
// ...
return 0;
}
You can use XWarpPointer to move the mouse cursor in an X window.
XWarpPointer(display, src_w, dest_w, src_x, src_y, src_width, src_height, dest_x,
dest_y)
Display *display;
Window src_w, dest_w;
int src_x, src_y;
unsigned int src_width, src_height;
int dest_x, dest_y;
All modern terminals should support ANSI escape sequences. For anything more complicated (and more portable), however, you should look into using a library such as ncurses.

Resources