4

下面的代码打开一个大小合适的窗口 w,h,但不在正确的位置 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
}

我用 g++ xwindowtest.cpp -lX11 编译了它,其中 g++ 是 4.6.2 版,并在 Debian GNU/Linux 下运行。

4

3 回答 3

8

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.

于 2013-02-26T12:47:27.313 回答
1

我通常先声明一个XSizeHints 并将 x,y 坐标等分配给hints.

创建 x 窗口时,您可以这样做

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

这对我来说总是适用于 100% 正确的窗口位置。

于 2013-02-12T18:02:44.103 回答
0

我有同样的问题。我只是从 X11 开始。也许其他有更多经验的人可以澄清为什么这样做(并且简单地为 XCreateSimpleWindow 指定 x, y 没有)。

这是我的修复:

disp 是你的显示器,win0 是你的 canvas_window:

XMoveWindow(disp, win0, 200, 200);

XSync (disp, FALSE);


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

XMoveWindow(disp, win0, 0, 0);

XSync (disp, FALSE);

... do something

当我运行此代码片段时,窗口会移动。您需要通过 XSync 遵循 XMoveWindow,以便正确处理请求(例如移动)。

于 2012-08-07T19:46:17.553 回答