I am creating an X11 window, which is then resized programmatically with XWindowResize:
#include <X11/Xlib.h>
#include <GL/gl.h>
#include <GL/glx.h>
#include <cassert>
#include <cstdio>
int main()
{
Display* display = XOpenDisplay(nullptr);
assert(display);
Window root = DefaultRootWindow(display);
assert(root);
GLint att[] = { GLX_RGBA, GLX_DEPTH_SIZE, 24, GLX_DOUBLEBUFFER, None };
XVisualInfo* vi = glXChooseVisual(display, 0, att);
assert(vi);
XSetWindowAttributes swa;
swa.colormap = XCreateColormap(display, root, vi->visual, AllocNone);
swa.event_mask = ExposureMask | KeyPressMask;
// create window with initial size 800 x 600
Window window = XCreateWindow(display, root, 0, 0, 800, 600, 0, vi->depth, InputOutput, vi->visual, CWColormap | CWEventMask, &swa);
XSelectInput(display, window, StructureNotifyMask | ResizeRedirectMask);
XMapWindow(display, window);
XFlush(display);
// resize window to new size 400 x 300
int result = XResizeWindow(display, window, 400, 300);
printf("XResizeWindow return value: %d\n", result);
if (result == BadValue) printf(" bad value!!!\n");
if (result == BadWindow) printf(" bad window!!!\n");
XEvent event;
XAnyEvent& ev = (XAnyEvent&)event;
while (true)
{
XNextEvent(display, &event);
if (ev.type == ResizeRequest)
{
XResizeRequestEvent& ev = (XResizeRequestEvent&)event;
printf("request to resize to %d x %d\n", ev.width, ev.height);
}
XWindowAttributes xwa;
XGetWindowAttributes(display, window, &xwa);
printf("position: %d, %d size: %d x %d\n", xwa.x, xwa.y, xwa.width, xwa.height);
}
}
This is not working as expected. The window decoration drawn by the window manager indicates that it is indeed resized to 400x300 pixels, however, XGetWindowAttributes reports the contrary (output below). Changing position and size manually with the mouse has the same effect: the resize request reports the correct size, but it is not reflected in the output of XGetWindowAttributes. The problem is that this affects the area in which mouse events are detected as well as OpenGL drawing (removed in order to have a minimal example).
XResizeWindow return value: 1
position: 1, 30 size: 800 x 600
position: 1, 30 size: 800 x 600
request to resize to 400 x 300
position: 1, 30 size: 800 x 600
position: 1, 30 size: 800 x 600
position: 1, 30 size: 800 x 600
Apparently I am doing it wrong. I'd appreciate any help on how to make this work. Do I have to do anything in order to honor the resize request? I have searched the web and stackoverflow for hours now without luck.
EDIT: It would already be helpful if someone could tell me whether the XResizeWindow return value of 1 indicates an error or not. I am unable to find documentation on the return value in case there is no error. Also, links to documentation containing this information are more than welcome!
Don't request ResizeRedirectMask. It is supposed to be requested by one client at a time, which is normally your window manager. Except WMs usually request SubstructureNotifyMaks on the root, which takes precedence over ResizeRedirectMask on the children, so that the latter is quite useless. I couldn't find one single example of a program, WM or otherwise, that uses ResizeRedirectMask.
If you do request ResizeRedirectMask, your window attributes may be stuck with a wrong size.
If you need to catch actual size changes, request StructureNotifyMask and process ConfigureNotify events.
Related
I am facing an issue with the SDL library and different resolution than 1920x1080.
I want to copy display an image of dimension 1080x608 at the center of a screen of resolution 1080x1920 (portrait).
I have only one plugged monitor screen.
I used the following command to switch screen from 1920x1080 to 1080x1920 :
xrandr --output DP-1 --mode 1920x1080 --rotate left --primary
I am using the following code to initialize the SDL renderer :
/**
* initialize everything so we are ready to display
*/
int SdlHandler::initialize(
unsigned int positionX,
unsigned int positionY,
unsigned int width,
unsigned int height,
bool showWindow,
std::string name) {
// Initialize SDL
if (SDL_Init(SDL_INIT_VIDEO) < 0) {
std::cerr << "SDL could not initialize! SDL_Error: " << SDL_GetError() << std::endl;
return -1;
}
// Size if the window
this->width = width;
this->height = height;
this->positionX = positionX;
this->positionY = positionY;
// Create the SDL window
// 0 and 0 are the position in X and Y
unsigned int flags = SDL_WINDOW_OPENGL | SDL_WINDOW_BORDERLESS;
if (showWindow) {
flags |= SDL_WINDOW_SHOWN;
} else {
flags |= SDL_WINDOW_HIDDEN;
}
this->window = SDL_CreateWindow(name.c_str(), this->positionX, this->positionY, this->width, this->height, flags);
// If there had been a problem, leave
if (!this->window) {
return -1;
}
// Create a new renderer
this->renderer = SDL_CreateRenderer(this->window, -1, SDL_RENDERER_ACCELERATED | SDL_RENDERER_PRESENTVSYNC);
// If there is an error creating it, just leave
if (!this->renderer) {
return -1;
}
// Setup the best for the SDL render quality
SDL_SetHint(SDL_HINT_RENDER_SCALE_QUALITY, "2");
return 0;
}
Then, i call the SDL_RenderCopy function to display the image. I pass it the created renderer created with theSDL_CreateRenderer on the above code :
// Create a window at 0,0 of dimension 1080x1920
this->initialize(0, 0, 1080, 1920, true, SDL_BASE_DISPLAY_WINDOW);
// Create the SDL Rectangle that will contain the image, at the center of the window
SDL_Rect *howToDraw = new SDL_Rect();
howToDraw->x = this->positionX + floor((this->width - this->imageWidth) / 2);
howToDraw->y = this->positionY + floor((this->height - this->imageHeight) / 2);
howToDraw->w = this->imageWidth;
howToDraw->h = this->imageHeight;
SDL_RenderCopy(this->renderer, this->texture, NULL, howToDraw);
But the axis seems to be at the wrong position, igot the following result :
EDIT AND SOLUTION
This was a bug related to Compton, the window manager, everything is working good without Compton ...
Since you are rotating your display using xrandr, we can consider this is a post processing step that will rotate everything after each framebuffer is rendered.
Because this post processing step takes a 1920x1080 image resolution as input, you should use the SDL at this resolution.
What if you change your code for:
// Create a window at 0,0 of dimension 1920x1080
this->initialize(0, 0, 1920, 1080, true, SDL_BASE_DISPLAY_WINDOW);
EDIT: I also understand that you want your image to start at the center of the window, but your are placing the middle of the image at the center of the window.
You should also try the following:
howToDraw->x = this->positionX + this->imageWidth / 2;
I've been at this for days now, but i just can't seem to figure out how to create a 32 bit root window so that I can use RGBA colors on the child window, and the child window cannot use 32-bit color depth (24-bit for RGB, and 8-bit for Alpha channel) if the parent, or in this case root window, does not have 32-bit color depth. I am using the following code to set the background of the root window to an RGB image which has a color depth of 24-bit, thus when I set XCreatePixmap to a color depth of 24 bit it just works, but i need this root window to have a color depth of 32-bit for alpha compositing:
/* displays an image or sets root background
* PUBLIC DOMAIN - CC0 http://creativecommons.org/publicdomain/zero/1.0/
* J.Mayo 2013
*
* gcc -Wall -W -g3 -o background background.c -lX11 -lImlib2
*
*/
#include <stdio.h>
#include <X11/Xlib.h>
#include <X11/Xutil.h>
#include <X11/extensions/Xcomposite.h>
#include <Imlib2.h>
struct screenAttributes {
int height;
int width;
};
struct screenAttributes screenAttr;
void initializeScreenAttributes(Screen *screen) {
screenAttr.height=screen->height;
screenAttr.width=screen->width;
}
int main(int argc, char **argv)
{
Imlib_Image img;
Display *dpy;
Pixmap pix;
Window root;
Screen *scn;
// Window topPanel;
int width, height;
const char *filename = "/sampleImage.png";
img = imlib_load_image(filename);
if (!img) {
fprintf(stderr, "%s:Unable to load image\n", filename);
goto usage;
}
imlib_context_set_image(img);
width = imlib_image_get_width();
height = imlib_image_get_height();
dpy = XOpenDisplay(NULL);
if (!dpy) return 0;
scn = DefaultScreenOfDisplay(dpy);
root = DefaultRootWindow(dpy);
pix = XCreatePixmap(dpy, root, width, height,32); //when depth is set to 24 it just works, but when it is set to 32 it fails.
//scale the image
initializeScreenAttributes(scn);
imlib_blend_image_onto_image(img,0,0,0,width,height,0,0,
screenAttr.width, screenAttr.height);
imlib_context_set_display(dpy);
imlib_context_set_visual(DefaultVisualOfScreen(scn));
imlib_context_set_colormap(DefaultColormapOfScreen(scn));
imlib_context_set_drawable(pix);
imlib_render_image_on_drawable(0, 0);
XSetWindowBackgroundPixmap(dpy, root, pix);
XClearWindow(dpy, root);
while (XPending(dpy)) {
XEvent ev;
XNextEvent(dpy, &ev);
}
XFreePixmap(dpy, pix);
imlib_free_image();
sleep(10);
//XFreePixmap(dpy, pix);
//imlib_free_image();
XCloseDisplay(dpy);
return 0;
usage:
fprintf(stderr, "usage: %s <image_file>\n", argv[0]);
return 1;
}
when I set XCreapePixmap to a color depth of 32-bit, I get:
X Error of failed request: BadMatch (invalid parameter attributes)
Major opcode of failed request: 130 (MIT-SHM)
Minor Opcode of failed request: 3 (X_ShmPutImage)
Serial number of failed request : 28
Current serial number in output stream: 29 xinit: connection to X server lost
So, In other words I'm not quite sure as to how to set the color depth of the root window to 32-bit and have a 24-bit RGB image set as the background of the root window.
Thanks!
P.S. I do not have any window managers or any desktop environment installed, so using any of the available tools in those is out of the question.
No. You don't have to have root window be depth 32 to have children be depth 32
too. Otherwise how on earth do you think windows can have alpha channels in a
compositor? How do you think this:
http://www.enlightenment.org/ss/e-5872c6ec3ddce1.54730231.png
is possible without 2 of those windows having 32bit depth? (the 2 on the left -
clock and translucent terminal). :)
The way translucency WORKS is a compositor intervenes (these days usually your
window manager) and is composites the 32bit windows on top (also possibly deals
with redrawing root window too at the bottom - it may depend though). so saying "I don't have a compositor/window manager so that's out of the question" is basically saying "I don't want to do the one and only thing I HAVE TO DO in order to get translucency" so I suggest you re-evaluate that position.
So what you want really is a compositor AND 32bit windows. Either use a
compositing window manager and then create 32bit windows, OR run a separate
compositor and your existing WM, or write your own compositor... (not going to
be much fun to get this right AND fast)...
Now to create an ARGB window you'll need help from XRender for the visual. Like the below where disp is your Xlib Display and parent is the parent Window (e.g. root):
Window win;
XSetWindowAttributes attr;
XWindowAttributes att;
XVisualInfo *xvi;
XVisualInfo vi_in;
int nvi, i, scr = 0;
XRenderPictFormat *fmt;
Visual *vis;
vi_in.screen = scr;
vi_in.depth = 32;
vi_in.class = TrueColor;
xvi = XGetVisualInfo(disp,
VisualScreenMask |
VisualDepthMask |
VisualClassMask,
&vi_in,
&nvi);
if (!xvi) return 0;
vis = NULL;
for (i = 0; i < nvi; i++)
{
fmt = XRenderFindVisualFormat(disp, xvi[i].visual);
if ((fmt->type == PictTypeDirect) && (fmt->direct.alphaMask))
{
vis = xvi[i].visual;
break;
}
}
XFree (xvi);
attr.backing_store = NotUseful;
attr.override_redirect = 0;
attr.colormap = XCreateColormap(disp, parent,
vis, AllocNone);
attr.border_pixel = 0;
attr.background_pixmap = None;
attr.bit_gravity = NorthWestGravity;
attr.win_gravity = NorthWestGravity;
attr.save_under = 0;
attr.do_not_propagate_mask = NoEventMask;
attr.event_mask = KeyPressMask |
KeyReleaseMask |
ButtonPressMask |
ButtonReleaseMask |
EnterWindowMask |
LeaveWindowMask |
PointerMotionMask |
ExposureMask |
VisibilityChangeMask |
StructureNotifyMask |
FocusChangeMask |
PropertyChangeMask |
ColormapChangeMask;
win = XCreateWindow(disp, parent,
x, y, w, h, 0,
32,
InputOutput,
vis,
CWBackingStore |
CWOverrideRedirect |
CWColormap |
CWBorderPixel |
CWBackPixmap |
CWSaveUnder |
CWDontPropagate |
CWEventMask |
CWBitGravity |
CWWinGravity,
&attr);
Code comes from here: https://git.enlightenment.org/core/efl.git/tree/src/lib/ecore_x/ecore_x_window.c#n1644
We used to have an XCB back-end and all this code in XCB, but we've given up on XCB after a decade or so. If you clone the above and dig through history you'll fine the ecore_x dir used to have xlib and xcb sub-dirs if you really want to dig that out.
This is why I wrote an xlib abstractor/detail filler because it's a lot less code to write if you hide common verbose Xlib usage behind simpler APIs.
Looks like you have exactly the same problem as I described here: How to upload 32 bit image to server-side pixmap
If you create 32-bit window and you have 24 bit root, you can't use DefaultVisualOfScreen / DefaultColormapOfScreen - they'l set visual/colormap that are valid for root (and thus, 24 bit).
imlib_context_set_visual(DefaultVisualOfScreen(scn));
imlib_context_set_colormap(DefaultColormapOfScreen(scn));
I'm not very familiar with imlib api, but it looks you should be able to create colormap for your window/pixmap manually and pass it to imlib
The easiest way to create a 32-bit-deep window:
XVisualInfo vinfo;
XMatchVisualInfo(display, DefaultScreen(display), 32, TrueColor, &vinfo);
Window win = XCreateWindow(display, DefaultRootWindow(display),
0, 0, width, height, 0,
vinfo.depth, // <---------------!!!
InputOutput,
vinfo.visual, // <---------------!!!
mask, &attr);
You cannot have the root window to have the depth you want — it already exists and has the depth it has.
Would like to offer a simpler solution (basically the same as #n.m. solution, but has some more code):
Display *d = XOpenDisplay(NULL);
Window root = DefaultRootWindow(d);
int default_screen = XDefaultScreen(d);
XSetWindowAttributes attrs;
attrs.override_redirect = true;
XVisualInfo vinfo;
if (!XMatchVisualInfo(d, DefaultScreen(d), 32, TrueColor, &vinfo)) {
printf("No visual found supporting 32 bit color, terminating\n");
exit(EXIT_FAILURE);
}
attrs.colormap = XCreateColormap(d, root, vinfo.visual, AllocNone);
attrs.background_pixel = 0;
attrs.border_pixel = 0;
// Window XCreateWindow(
// Display *display, Window parent,
// int x, int y, unsigned int width, unsigned int height, unsigned int border_width,
// int depth, unsigned int class,
// Visual *visual,
// unsigned long valuemask, XSetWindowAttributes *attributes
// );
Window overlay = XCreateWindow(
d, root,
0, 0, 200, 200, 0,
vinfo.depth, InputOutput,
vinfo.visual,
CWOverrideRedirect | CWColormap | CWBackPixel | CWBorderPixel, &attrs
);
Basically, you need to specify a color map, background pixel (CWBackPixel) and border pixel, in addition to getting the proper visual. Instead of looping over all available visuals with XGetVisualInfo, XMatchVisualInfo does the work for you. Note that I am not performing error checks for this process, which you should implement in production
I am trying to make a borderless window in Qt5.6.0, with aero-snap functionality.
Everything works, except when I maximize the window : it is too big.
My screen resolution is 2560x1440, so the window should be sized 2560x1400 (40 Pixels for the Taskbar), but in the WM_SIZE message, the new size is 2576x1416.
So the window is exactly 8 pixels too big in every direction.
This also means that the window is not aligned in the top-left corner, it is exactly 8 pixels off-screen in both directions.
I can't find a solution for this problem, everything I have tried doesn't work and causes bugs.
The only thing that fixes this is to remove the WS_CAPTION and WS_THICKFRAME styles, but then I lose the areo snap functionality.
I somehow have to tell Qt or DWM to make the window 16 pixels smaller and move it 8 pixels right, and bottom. Does anybody have an idea on how to do that?
I somehow have to tell Qt or DWM to make the window 16 pixels smaller
and move it 8 pixels right, and bottom. Does anybody have an idea on
how to do that?
DWM is Desktop Window Manager? Then the platform is Windows then.
As long as it is about Qt 5.6 and you very likely talking about the widget with Qt::CustomizeWindowHint attribute set then there is a known bug in Qt which is not fixed yet:
https://bugreports.qt.io/browse/QTBUG-4362
I stumbled upon that bug a couple of times and the workaround proposed by BiTOk at the link above worked for me.
My first try, was setting the window geometry to the available geometry:
QRect rect = QApplication::desktop()->availableGeometry();
setGeometry(rect.left() , rect.top(), rect.right(), rect.bottom());
The only Problem is that the window is a pixel too small on the right and bottom side and
setGeometry(rect.left() , rect.top(), rect.right() + 1, rect.bottom() + 1);
gives me an error:
QWindowsWindow::setGeometry: Unable to set geometry 2560x1400+0+0 on QWidgetWindow/'MainWindowWindow'. Resulting geometry: 2576x1416+-8+-8 (frame: 0, 0, 0, 0, custom margin: 0, 0, 0, 0, minimum size: 45x13, maximum size: 16777215x16777215)
Then I looked at the rectangle coordinates of Visual Studio 2015 and they are the same size as my implementation of a borderless window, 8 pixels larger in every direction.
I can give the contents of my window a margin of 8 so it doesn't clip out of the screen if the window is maximized and set the window region:
setContentsMargins({ 8, 8, 8, 8 });
HRGN WinRgn;
RECT winrect;
GetClientRect(hwnd, &winrect);
WinRgn = CreateRectRgn(8, 8, winrect.right - 8, winrect.bottom - 8);
SetWindowRgn(hwnd, WinRgn, true);
When the window gets restored, we need to reset the previous changes.
The result is:
case WM_SIZE:
WINDOWPLACEMENT wp;
wp.length = sizeof(WINDOWPLACEMENT);
GetWindowPlacement(hwnd, &wp);
if (wp.showCmd == SW_MAXIMIZE) {
setContentsMargins({ 8, 8, 8, 8 });
HRGN WinRgn;
RECT winrect;
GetClientRect(hwnd, &winrect);
WinRgn = CreateRectRgn(8, 8, winrect.right - 8, winrect.bottom - 8);
SetWindowRgn(hwnd, WinRgn, true);
UpdateWindow(hwnd);
is_fullscreen = true;
} else {
if (is_fullscreen) {
setContentsMargins({ 0, 0, 0, 0 });
SetWindowRgn(hwnd, NULL, true);
is_fullscreen = false;
}
}
break;
Other posts have already answered the question, but I would just like to add that it might be a good idea to use GetSystemMetrics rather than a hard-coded value of 8.
Example
#include <Windows.h>
void MyWindow::changeEvent(QEvent* ev) {
if (ev->type() == QEvent::WindowStateChange) {
const auto state = windowState();
if(state & Qt::WindowMaximized) {
const int x = GetSystemMetrics(SM_CXFRAME) + GetSystemMetrics(SM_CXPADDEDBORDER);
const int y = GetSystemMetrics(SM_CYFRAME) + GetSystemMetrics(SM_CXPADDEDBORDER);
setContentsMargins({x, y, x, y});
}
else {
setContentsMargins({0, 0, 0, 0});
}
}
Like attached my photo, I want to get "Windowed Window's Screen coordinate of each Corner in X-window". (I draw red dots, which I want to get as Screen coordinates, in the following image. What I am going to do later is to get exact middle point of my OpenGL window in 2D screen coordinate.
I tried following code already:
int* getWindowPos(Display *dpy) {
int winPos[2];
Window myWin;
myWin = XRootWindow(dpy, 0);
XWindowAttributes xwa;
XGetWindowAttributes(dpy, myWin, &xwa);
// printf("%d %d\n", xwa.x, xwa.y);
return winPos;
}
but this "XWindowAttributes" always gives me 0 in x point ,0 in y point, and width 1600 and height 900, which is same as my screen resolution.
following is what I coded to create this windowed window.
GLWin.win = XCreateWindow(GLWin.dpy, RootWindow(GLWin.dpy, vi->screen),
0, 0, 800, 600, 0, vi->depth, InputOutput, vi->visual,
CWBorderPixel | CWColormap | CWEventMask, &GLWin.attr);
You're storing your window into GLWin.win, but are querying the root window for its size and location. The "root window" is the full screen background window (desktop), so it makes sense that it's returning your screen resolution. Just pass your actual window (GLWin.win) to XGetAttributes() if you want those dimensions.
I'm using Ubuntu 12.04 in a VM.
Upper left is never correct. Width and height are correct about 90% of the time.
XMoveWindow and friends have no effect on the rendered position of the window.
Source:
#include <stdio.h>
#include <GL/gl.h>
#include <GL/glx.h>
#include <X11/Xlib.h>
#include <X11/Xutil.h>
#include <X11/X.h>
int main(int argc, char **argv)
{
Display *disp = XOpenDisplay(0);
GLint attr[] = {GLX_RGBA, GLX_DEPTH_SIZE, 24, GX_DOUBLEBUFFER, None};
XVisualInfo *vinfo = glXChooseVisual(disp,0,attr);
Window rootWnd = DefaultRootWindow(disp);
XSetWindowAttributes setWndAttr = {0};
setWndAttr.colormap = XCreateColormap(disp,rootWnd,vinfo->visual,AllocNone);
setWndAttr.event_mask =
ExposureMask|
StructureNotifyMask;
Window wnd = XCreateWindow(
disp,rootWnd,
64,64, // can be ignored (asinine)
512,512,
0,vinfo->depth,
InputOutput,
vinfo->visual,
CWColormap|CWEventMask,
&setWndAttr
);
XStoreName(disp,wnd,"What is this crap?");
XMapWindow(disp,wnd);
// WMs allowed to completely ignore these, too?
//XMoveWindow(disp,wnd,128,128);
//XMoveResizeWindow(disp,wnd,128,128,256,256);
Atom closeWndAtom = XInternAtom(disp,"WM_DELETE_WINDOW",0);
XSetWMProtocols(disp,wnd,&closeWndAtom,1);
GLXContext ctx = glCreateContext(disp,vinfo,0,GL_TRUE);
glXMakeCurrent(disp,wnd,ctx);
bool run = true;
XEvent evt;
while(run){
XNextEvent(disp,&evt);
switch(evt.type){
case Expose:
{
XWindowAttributes wndAttr;
XGetWindowAttributes(disp,wnd,&wndAttr);
// these are NEVER correct (0,0 most of the time)
printf("%i, %i\n",wndAttr.x,wndAttr.y);
// these are correct, most of the time
//
// occasionally, either width or height will be 0
glViewport(0,0,wndAttr.width,wndAttr.height);
glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT);
glBegin(GL_TRIANGLES);
glColor3f(1,0,0);
glVertex2f(0,0);
glColor3f(0,1,0);
glVertex2f(1,0);
glColor3f(0,0,1);
glVertex2f(0,1);
glEnd();
glXSwapBuffers(disp,wnd);
}break;
case ClientMessage:
{
run = false;
}break;
}
}
glXDestroyContext(disp,ctx);
XDestroyWindow(disp,wnd);
XCloseDisplay(disp);
return 0;
}
Note: There might be a spelling error to two, as pasting from within the VM wouldn't format correctly. As a result, I had to re-type it.
EDIT:
Because clarity is needed here: I don't care what the window manager does with the position I give it, I am interested in retrieving this information from the window manager reliably. The position I am given does not correspond to the rendered position of the window on the screen. For example: The window appears at the lower right of the screen, and the coordinates returned to me are (0,0). Moving the window around using the mouse doesn't change what XGetWindowAttributes returns.
It seems you are polling window information from Expose event, which may not have newest information about window at the time. Use ConfigureNotify event and it's properties to get updated position and size:
// you need to have this in your event mask(you've already got that):
EVENT_MASK |= StructureNotifyMask;
// in your event loop
// ...
case ConfigureNotify: // resize or move event
printf("x: %d, y:%d, width: %d, height: %d\n",
event.xconfigure.x,
event.xconfigure.y,
event.xconfigure.width,
event.xconfigure.height);
break;
I think, one of the option is to use XTranslateCoordinates:
XTranslateCoordinates(dpy,
wnd, // get position for this window
root_window, // something like macro: DefaultRootWindow(dpy)
0, 0, // local left top coordinates of the wnd
&dest_x, // these is position of wnd in root_window
&dest_y, // ...
&unused);
You also can use XGetGeometry instead of XGetWindowAttributes to get left, top, width and height of a drawable. As far as I know XGetWindowAttributes calls XGetGeometry to retrieve some of the attributes.
I know, I'm necroposter, but I was also looking for the answer and found out that the incorrect coordinates are related to Window Manager.
{
case ConfigureNotify :
printf("%d, %d : %u, %u\n",
event.xconfigure.x, event.xconfigure.y,
event.xconfigure.width, event.xconfigure.height);
break;
}
# Moving window
353, 100 : 791, 600
363, 113 : 791, 600
# Changing window size
1, 24 : 791, 600 << Pay attention to this
363, 113 : 791, 600
363, 113 : 791, 600
For the additional info you need to read ICCCM (4.1.5. Configuring the Window, 4.2.3. Window Move, 4.2.4. Window Resize) https://tronche.com/gui/x/icccm/sec-4.html#s-4.1.5