Cannot get XCreateSimpleWindow to open window at t

2019-04-11 00:49发布

The following code opens a window of the right size, w,h, but not at the correct position, x,y.

#include <iostream>
#include <X11/Xlib.h>
#include <X11/Xutil.h>
#include <X11/Xresource.h>
using namespace std;

int main(int argc, char* argv[]){
  Display *display; // A connection to X server
  int screen_number;
  Window canvas_window;
  unsigned long white_pixel;
  unsigned long black_pixel;

  display = XOpenDisplay(NULL);    // Connect X server by opening a display

  if(!display){
    cerr<<"Unable to connect X server\n";
    return 1;
  }

  screen_number = DefaultScreen(display);
  white_pixel = WhitePixel(display, screen_number);
  black_pixel = BlackPixel(display, screen_number);


  int x=0, y=100, w=300, h=400;

  canvas_window = XCreateSimpleWindow(display,
                                      RootWindow(display, screen_number),
                                      x,y,  // top left corner
                                      w,h,  // width and height
                                      2,    // border width
                                      black_pixel,
                                      white_pixel);

  XMapWindow(display, canvas_window);    // Map canvas window to display
  XSync(display, False);

  cin >> x;   // just so that the program does not end
}

I compiled this with g++ xwindowtest.cpp -lX11 where g++ is version 4.6.2 and ran under Debian GNU/Linux.

标签: x11
3条回答
唯我独甜
2楼-- · 2019-04-11 01:18

The above solution is sort of correct, but not complete.

Creating a new top-level window on the desktop, and creating a new (child) window within the top-level window of your application use the same XCreateSimpleWindow() call, but the actual behaviour can be different.

When creating a new child window within your application you are in charge, and the origin coordinates (relative to its parent window's origin) and size you give for the new window will be honoured. In other words the window will go where you want it to.

However when creating a new top-level window on the desktop you have to deal with the pesky window manager, for example Motif, KDE, Gnome, etc. This intervenes when you create a top-level window to add borders ("decoration"), title, possibly icons, etc. More to the point it will, by default, ignore your requested origin coordinates in most cases and put the new window where it wants rather than where you asked it to put it. It is only when it has been mapped (somewhere) that you can then move it with XMoveWindow().

To avoid this you can ask, or in X11-speak "Hint to", the Window manager that "no, I want you to put the window where I ask, not where you want to put it". You do this with the following sequence:

(1) Define a XSizeHints structure. (2) Set the flags bit in this structure with a mask of what you want to specify (3) Populate the relevant arguments (4) Call XSetNormalHints() on the newly created window (before you map it).

So in C code you would do:

XSizeHints    my_hints = {0};

my_hints.flags  = PPosition | PSize;     /* I want to specify position and size */
my_hints.x      = wanted_x_origin;       /* The origin and size coords I want */
my_hints.y      = wanted_y_origin;
my_hints.width  = wanted_width;
my_hints.height = wanted_height;

XSetNormalHints(disp, new_window, &my_hints);  /* Where new_window is the new window */

Then map it and - hopefully - it will be where you want it.

查看更多
手持菜刀,她持情操
3楼-- · 2019-04-11 01:21

I had the same problem. I am just starting with X11. Maybe others with more experience can clarify why this works (and simply specifying the x, y for XCreateSimpleWindow does not).

Here's my fix:

disp is your display, win0 is your canvas_window:

XMoveWindow(disp, win0, 200, 200);

XSync (disp, FALSE);


 ..... do something .....

XMoveWindow(disp, win0, 0, 0);

XSync (disp, FALSE);

... do something

When I run this code snippet, the window moves. You need to follow the XMoveWindow by XSync so that requests (such as a move) are handled appropriately.

查看更多
祖国的老花朵
4楼-- · 2019-04-11 01:30

I usually declare a XSizeHints first and assign x,y coordinates etc to hints.

When creating x window you could do

 XCreateSimpleWindow(display, 
                     DefaultRootWindow(display), 
                     hints.x, hints.y, 
                     hints.width,hints.height, 
                     borderWidth, 
                     blackPixel, whitePixel)

That always works for me with 100% correct windows location.

查看更多
登录 后发表回答