I've followed How to upload 32 bit image to server-side pixmap and XDestroy(ximg); segfaults.
#include <stdlib.h>
#include <string.h>
#include <X11/Xlib.h>
#include <X11/Xutil.h>
int
main(int argc, char **argv) {
Display *dpy;
Window root;
Screen *screen;
GC gc;
XImage *ximg;
Pixmap pm;
int depth, h, w;
char *img;
dpy = XOpenDisplay(0);
if (!dpy) {
fputs("cannot open display\n", stderr);
return 1;
}
screen = DefaultScreenOfDisplay(dpy);
h = HeightOfScreen(screen);
w = WidthOfScreen(screen);
root = DefaultRootWindow(dpy);
depth = DefaultDepth(dpy, DefaultScreen(dpy));
img = malloc(depth/8 * h * w);
if (img == NULL) {
perror("malloc() failed");
return 1;
}
memset(img, 0xFF, depth/8 * h * w);
ximg = XCreateImage(dpy, CopyFromParent, depth, ZPixmap, 0, img, w, h, 32, 0);
pm = XCreatePixmap(dpy, root, w, h, depth);
gc = XCreateGC(dpy, pm, 0, NULL);
XPutImage(dpy, pm, gc, ximg, 0, 0, 0, 0, w, h);
XCopyArea(dpy, pm, root, gc, 0, 0, w, h, 0, 0);
free(img);
XFreePixmap(dpy, pm);
XDestroyImage(ximg);
XFreeGC(dpy, gc);
XCloseDisplay(dpy);
return 0;
}
Also, according to How to draw an image from file on window with Xlib I should include something like
XEvent ev;
while (1) {
XNextEvent(dpy, &ev);
if (ev.type == Expose)
XCopyArea(dpy, pm, root, gc, 0, 0, w, h, 0, 0);
}
before cleaning up, but how/when do I give system resources back then?
UPDATE
Apparently free(img); was causing the segfault, because XDestroyImage(ximg); is itself freeing the image. But still, where do I put that event loop and what terminating condition should it have so that I can free system resources accordingly?
According to XDestroyImage(3):
Note that when the image is created using XCreateImage, XGetImage, or XSubImage, the destroy procedure that the XDestroyImage function calls frees both the image structure and the data pointed to by the image structure.
So free(img); is redundant and will cause a SegFault.
Related
I am trying to create a simple X11 window, which should display a PNG file with transparent areas. I want the window itself to have no (opaque) background, so that the transparent areas in the PNG shows what there is behind the window.
tl;dr I cannot put an image on a semi-transparent window; it gives "Bad Match".
I can successfully create a semi-transparent window using XCreateWindow and XMatchVisualInfo :
XSetWindowAttributes attr;
attr.colormap = XCreateColormap(display, DefaultRootWindow(display),
vinfo.visual, AllocNone);
attr.border_pixel = 0;
attr.background_pixel = 0x80800000; // Red, semi-transparent
Window window = XCreateWindow(display, DefaultRootWindow(display), 0, 0,
width, height, 0, vinfo.depth, InputOutput, vinfo.visual,
CWColormap | CWBorderPixel | CWBackPixel, &attr);
(Full source code below)
I then create an image using :
// "image32" is a generated image - see source code below
XImage *ximage = XCreateImage(display, visual, DefaultDepth(display,DefaultScreen(display)),
ZPixmap, 0, image32, width, height, 32, 0);
And display the image during the Expose event :
XPutImage(display, window, DefaultGC(display, 0), ximage,
0, 0, 0, 0, width, height);
I compile with gcc test.c -L/usr/X11R6/lib -lX11 -lXrandr -o test and run with ./test :
X Error of failed request: BadMatch (invalid parameter attributes)
Major opcode of failed request: 72 (X_PutImage)
Serial number of failed request: 11
Current serial number in output stream: 12
Note : If I replace the lines creating the window (XCreateWindow) with these :
Window window = XCreateSimpleWindow(display, RootWindow(display, 0), 0, 0,
width, height, 1, 0, 0);
It displays a window correctly; however, there is no transparency.
I read the docs about XCreateWindow, XPutImage, XCreateImage and tried playing around with multiple parameters, unsuccessfully.
I have read this SO question and tried playing around with color depth; since the docs mentionned "Bad Match" can be also thrown for incorrect visual, I have checked that the same visual was sent at all places in my code.
Any help is appreciated.
Thanks!
Full source code :
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <X11/Xlib.h>
#include <X11/Xutil.h>
// Window size
int height = 256, width = 256;
XImage *CreateTrueColorImage(Display *display, Visual *visual)
{
int i, j;
unsigned char *image32=(unsigned char *)malloc(width*height*4);
unsigned char *p=image32;
for(i=0; i<width; i++)
{
for(j=0; j<height;j++)
{
*p++ = i;
*p++ = i;
*p++ = j;
*p++ = j; // alpha channel (should progressively get transparent towards left)
}
}
// Replacing "DefaultDepth(display,DefaultScreen(display))" with a hardcoded
// 24 or 32 still doesn't work with XCreateWindow. XCreateSimpleWindow works
// with hardcoded 24, but not 32.
return XCreateImage(display, visual, DefaultDepth(display,DefaultScreen(display)),
ZPixmap, 0, image32, width, height, 32, 0);
}
int main(int argc, char **argv)
{
XImage *ximage;
Display *display = XOpenDisplay(NULL);
Visual *visual = DefaultVisual(display, 0);
XVisualInfo vinfo;
XMatchVisualInfo(display, DefaultScreen(display), 32, TrueColor, &vinfo);
XSetWindowAttributes attr;
attr.colormap = XCreateColormap(display, DefaultRootWindow(display),
vinfo.visual, AllocNone);
attr.border_pixel = 0;
attr.background_pixel = 0x80800000; // Red, semi-transparent
//Window window = XCreateSimpleWindow(display, RootWindow(display, 0), 0, 0,
// width, height, 1, 0, 0);
Window window = XCreateWindow(display, DefaultRootWindow(display), 0, 0,
width, height, 0, vinfo.depth, InputOutput, vinfo.visual,
CWColormap | CWBorderPixel | CWBackPixel, &attr);
ximage = CreateTrueColorImage(display, vinfo.visual);
XSelectInput(display, window, ButtonPressMask|ExposureMask);
XMapWindow(display, window);
while(1)
{
XEvent event;
XNextEvent(display, &event);
switch(event.type)
{
case Expose:
XPutImage(display, window, DefaultGC(display, 0), ximage,
0, 0, 0, 0, width, height);
break;
case ButtonPress:
exit(0);
}
}
}
I managed to make it work by making two changes.
First, instead of using DefaultGC(display, 0) you should create a GC for your specific window.
GC gc = XCreateGC(display, window, 0, 0);
With that if you hardcode the depth of XCreateImage to 32 it should work correctly.
And you can also use the depth provided by XVisualInfo like so
XCreateImage(display, vinfo.visual, vinfo.depth,
ZPixmap, 0, image32, width, height, 32, 0);
This is a working example of X11 code that handles Ctrl-q event to quit application:
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <X11/Xlib.h>
#include <X11/Xutil.h>
#include <X11/Xos.h>
void exitOnCondition(char cond, const char *msg, int exitCode, Display *dpy, Window *w, GC *gc) {
if(cond) {
printf("%s\n", msg);
if(dpy && gc) XFreeGC(dpy, *gc);
if(dpy && w) XDestroyWindow(dpy, *w);
if(dpy) XCloseDisplay(dpy);
exit(exitCode);
}
}
int main(int argc, char **argv) {
Display *dpy = XOpenDisplay(0);
exitOnCondition(dpy == 0, "Error: XOpenDisplay failed", -1, dpy, 0, 0);
int blackColor = BlackPixel(dpy, DefaultScreen(dpy));
int whiteColor = WhitePixel(dpy, DefaultScreen(dpy));
Window w = XCreateSimpleWindow(dpy, DefaultRootWindow(dpy), 0, 0,
200, 100, 0, blackColor, blackColor);
//Tell X Server to send MapNotify events
XSelectInput(dpy, w, StructureNotifyMask | KeyPressMask);
//Make window appear
XMapWindow(dpy, w);
//Graphics Context
GC gc = XCreateGC(dpy, w, 0, 0);
//Set white color for drawing
XSetForeground(dpy, gc, whiteColor);
//Wait for the MapNotify event
for(;;) {
XEvent e;
XNextEvent(dpy, &e);
if (e.type == MapNotify) {
break;
}
}
//Draw the line
XDrawLine(dpy, w, gc, 10, 60, 180, 20);
//Send the "DrawLine" request to the server
XFlush(dpy);
char text[255];
XEvent e;
KeySym key;
int numKeys = 0;
for(;;) {
XNextEvent(dpy, &e);
if(e.type == KeyPress) {
//With modifier XLookupString will return garbage(?) in text[0] and key as latin1
if((numKeys = XLookupString(&e.xkey, text, 255, &key, 0))) {
printf("lookup returned:\n");
for(int i = 0; i < numKeys; i++) {
printf("text[%d]=%x\n", i, text[i]);
}
if(e.xkey.state == ControlMask && key == XK_q) {
exitOnCondition(1, "C-Q pressed", 0, dpy, &w, &gc);
}
}
}
}
XFreeGC(dpy, gc);
XDestroyWindow(dpy,w);
XCloseDisplay(dpy);
}
Will this code correctly handle Ctrl-q event on any system?
Can I use e.xkey.state to check for Ctrl modifier after XLookupString for any keyboard layout even when Ctrl is rebound to CAPS Lock(or anything else)?
Why does XLookupString return one symbol text[0]==0x11 for Ctrl-q event and not text[0]==CtrlModifierCode text[1]=='q'?
XLookupString returns a sequence of ISO-8859-1 characters (at least according to the manual I have; I do not know how up-to-date it is). There is no character code in ISO-8859-1 for the "ctrl" key by itself. Strictly speaking, there isn't one for the ctrl-q combination either, but tradition dictates that ctrl + (A...Z) map to the 1...26 range.
I'm trying to use the Cairo graphics library on Linux in C to make a pretty lightweight x11 GUI.
After trying very hard to follow the woefully incomplete guide that cairo gives for x11, this is the best I've got:
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <cairo.h>
#include <cairo-xlib.h>
#include <X11/Xlib.h>
#include <X11/extensions/Xrender.h>
#include <X11/extensions/renderproto.h>
//This function should give us a new x11 surface to draw on.
cairo_surface_t* create_x11_surface(int x, int y)
{
Display* d;
Drawable da;
int screen;
cairo_surface_t* sfc;
if((d = XOpenDisplay(NULL)) == NULL)
{
printf("failed to open display\n");
exit(1);
}
screen = DefaultScreen(d);
da = XCreateSimpleWindow(d, DefaultRootWindow(d), 0, 0, x, y, 0, 0, 0);
XSelectInput(d, da, ButtonPressMask | KeyPressMask);
XMapWindow(d, da);
sfc = cairo_xlib_surface_create(d, da, DefaultVisual(d, screen), x, y);
cairo_xlib_surface_set_size(sfc, x, y);
return sfc;
}
int main(int argc, char** argv)
{
//create a new cairo surface in an x11 window as well as a cairo_t* to draw
//on the x11 window with.
cairo_surface_t* surface = create_x11_surface(300, 200);
cairo_t* cr = cairo_create(surface);
while(1)
{
//save the empty drawing for the next time through the loop.
cairo_push_group(cr);
//draw some text
cairo_select_font_face(cr, "serif", CAIRO_FONT_SLANT_NORMAL, CAIRO_FONT_WEIGHT_BOLD);
cairo_set_font_size(cr, 32.0);
cairo_set_source_rgb(cr, 0, 0, 1.0);
cairo_move_to(cr, 10.0, 25.0);
if((argc == 2) && (strnlen(argv[1], 100) < 50))
cairo_show_text(cr, argv[1]);
else
cairo_show_text(cr, "usage: ./p1 <string>");
//put the drawn text onto the screen(?)
cairo_pop_group_to_source(cr);
cairo_paint(cr);
cairo_surface_flush(surface);
//pause for a little bit.
int c = getchar();
//change the text around so we can see the screen update.
for(int i = 0; i < strnlen(argv[1], 100); i++)
{
argv[1][i] = argv[1][i + 1];
}
if(c == 'q')
{
break;
}
}
cairo_surface_destroy(surface);
return 0;
}
On Linux systems that have Cairo installed, it can be compiled with
gcc -o myprog $(pkg-config --cflags --libs cairo x11) -std=gnu99 main.c
And it should be run with a single argument.
For reasons I don't understand at all, inserting the line
cairo_pop_group_to_source(cr);
cairo_paint(cr);
cairo_surface_write_to_png (surface, "hello.png"); //<--------- inserted
cairo_surface_flush(surface);
Puts something on the screen, but there are 2 problems:
Text that I draw with this method is persistent, creating a smearing effect.
I don't want some .png file mediating between my program and an x11 window. Data should be sent directly!
Several issues:
In X11, the X11 server doesn't save what you drew to a window, but instead sends an ExposeEvent to your window that tells it to redraw. This means you get a black window, because you do not handle this event.
getchar only gives you something after a line break, so just typing something won't help.
libX11 buffers stuff and only sends it to the X11 server when you wait for an event (or the buffer fills up). Since you never wait for an event, it never flushes. Calling XFlush explicitly helps.
The group that you push is useless. Just get rid of it.
Your code to move the string one direction to the left easily goes beyond the end of the string. You apparently know this already, because you 'fixed' this with a strnlen.
Here is a little better solution, but it still gives you an initially black window, because you draw to it before it is mapped:
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <cairo-xlib.h>
#include <X11/Xlib.h>
//This function should give us a new x11 surface to draw on.
cairo_surface_t* create_x11_surface(Display *d, int x, int y)
{
Drawable da;
int screen;
cairo_surface_t* sfc;
screen = DefaultScreen(d);
da = XCreateSimpleWindow(d, DefaultRootWindow(d), 0, 0, x, y, 0, 0, 0);
XSelectInput(d, da, ButtonPressMask | KeyPressMask);
XMapWindow(d, da);
sfc = cairo_xlib_surface_create(d, da, DefaultVisual(d, screen), x, y);
return sfc;
}
int main(int argc, char** argv)
{
Display *d = XOpenDisplay(NULL);
if (d == NULL) {
fprintf(stderr, "Failed to open display\n");
return 1;
}
//create a new cairo surface in an x11 window as well as a cairo_t* to draw
//on the x11 window with.
cairo_surface_t* surface = create_x11_surface(d, 300, 200);
cairo_t* cr = cairo_create(surface);
char *text = argv[1];
size_t text_len = 0;
if (argc != 2)
text = NULL;
else
text_len = strlen(text);
while(1)
{
// Clear the background
cairo_set_source_rgb(cr, 0, 0, 0);
cairo_paint(cr);
//draw some text
cairo_select_font_face(cr, "serif", CAIRO_FONT_SLANT_NORMAL, CAIRO_FONT_WEIGHT_BOLD);
cairo_set_font_size(cr, 32.0);
cairo_set_source_rgb(cr, 0, 0, 1.0);
cairo_move_to(cr, 10.0, 25.0);
if (text)
cairo_show_text(cr, text);
else
cairo_show_text(cr, "usage: ./p1 <string>");
cairo_surface_flush(surface);
XFlush(d);
//pause for a little bit.
int c = getchar();
//change the text around so we can see the screen update.
memmove(text, &text[1], text_len);
if (text_len > 0)
text_len--;
printf("got char %c\n", c);
if(c == 'q')
{
break;
}
}
// XXX: Lots of other stuff isn't properly destroyed here
cairo_surface_destroy(surface);
return 0;
}
Edit: Also, why exactly do you feel like cairo only gives you a woefully incomplete guide? It tells you how to get the cairo parts working and it also explains you some parts about X11, even though you should already know those if you want to use cairo-x11. That's none of its business. The guide you linked to even provides a complete, working and self-contained example: https://www.cypherpunk.at/files/2014/11/cairo_xlib_simple.c
I've you would have read the complete text of this "imcomplete guide" you would have seen that there is a link to the full sample: https://www.cypherpunk.at/files/2014/11/cairo_xlib_simple.c .
In SDL2 I want to be able to draw changes to one buffer rather than redraw the whole image to two different buffers as my setup seems to be doing. Below is a really quick test which shows the unwanted behavior:
#include <stdlib.h>
#include <stdio.h>
#include <unistd.h>
#include <SDL.h>
// Compile: gcc test.c -I/usr/local/include/SDL2 -L/usr/local/lib -lSDL2
void putPixel(SDL_Renderer *renderer, int x, int y)
{
SDL_SetRenderDrawColor(renderer, 255,255,255,255);
SDL_RenderDrawPoint(renderer, x, y);
}
int main(int argc, char* argv[]) {
int width = 640;
int height = 480;
SDL_Window *window = SDL_CreateWindow("Test", 0,0,width,height, 0);
if (window == NULL)
{
return -1;
}
SDL_Renderer *renderer = SDL_CreateRenderer(window, -1, SDL_RENDERER_ACCELERATED);
if (renderer == NULL)
{
return -2;
}
SDL_SetRenderDrawBlendMode(renderer,SDL_BLENDMODE_BLEND);
SDL_SetRenderDrawColor(renderer, 0, 0, 0, 255);
SDL_RenderClear(renderer);
for(int x=0;x<8;x++)
{
for(int y=0;y<10;y++)
{
putPixel(renderer,40+x*10,50+y);
}
SDL_RenderPresent(renderer);
sleep(1);
}
SDL_Quit();
return 0;
}
The output from this is two alternating screens. It is obviously using a double buffer which means I have to clear and redraw to get the output I want. After each cycle of the for...loop I wanted to add a line to the buffer - there should have been 8 lines at the end of the program running. In this case I got 4 on one buffer and 4 on another. I don't want to redraw the previous lines again either, hence the need for one buffer:
This uses a texture as a buffer and copies this to the screen when done.
#include <stdlib.h>
#include <stdio.h>
#include <unistd.h>
#include <SDL.h>
// Compile: gcc test.c -I/usr/local/include/SDL2 -L/usr/local/lib -lSDL2
void putPixel(SDL_Renderer *renderer, int x, int y)
{
SDL_SetRenderDrawColor(renderer, 255,255,255,255);
SDL_RenderDrawPoint(renderer, x, y);
}
int main(int argc, char* argv[]) {
int width = 640;
int height = 480;
SDL_Window *window = SDL_CreateWindow("Test", 0,0,width,height, 0);
if (window == NULL)
{
return -1;
}
SDL_Renderer *renderer = SDL_CreateRenderer(window, -1, SDL_RENDERER_ACCELERATED | SDL_RENDERER_TARGETTEXTURE);
if (renderer == NULL)
{
return -2;
}
SDL_SetRenderDrawBlendMode(renderer,SDL_BLENDMODE_BLEND);
/* Create texture for display */
SDL_Texture *display = SDL_CreateTexture(renderer, SDL_PIXELFORMAT_RGBA8888, SDL_TEXTUREACCESS_TARGET, width, height);
SDL_SetRenderTarget(renderer, display);
SDL_SetRenderDrawColor(renderer, 0, 0, 0, 255);
SDL_RenderClear(renderer);
for(int x=0;x<8;x++)
{
SDL_SetRenderTarget(renderer, display);
for(int y=0;y<10;y++)
{
putPixel(renderer,40+x*10,50+y);
}
SDL_SetRenderTarget(renderer, NULL);
SDL_RenderCopy(renderer, display, NULL, NULL);
SDL_RenderPresent(renderer);
sleep(1);
}
SDL_Quit();
return 0;
}
The output from this is below:
I'm trying to create server-side RGBA pixmap from client side buffer. CreatePixmap & CreateImage work ok for 32 and 24 bit, but XPutImage result in Match Error returned by server
X Error of failed request: BadMatch (invalid parameter attributes)
Major opcode of failed request: 72 (X_PutImage)
Serial number of failed request: 8
Current serial number in output stream: 8
server does support 32 bit pixmaps (xdpyinfo output: https://gist.github.com/2582961). Same behaviour on ubuntu 12.04 (X.Org version: 1.11.3) and OSX with X.app (X.Org version: 1.10.3)
Why following code fails?
#include <stdlib.h>
#include <X11/Xlib.h>
int main(int argc, char **argv)
{
int width = 100;
int height = 100;
int depth = 32; // works fine with depth = 24
int bitmap_pad = 32; // 32 for 24 and 32 bpp, 16, for 15&16
int bytes_per_line = 0; // number of bytes in the client image between the start of one scanline and the start of the next
Display *display=XOpenDisplay(0);
unsigned char *image32=(unsigned char *)malloc(width*height*4);
XImage *img = XCreateImage(display, CopyFromParent, depth, ZPixmap, 0, image32, width, height, bitmap_pad, bytes_per_line);
Pixmap p = XCreatePixmap(display, XDefaultRootWindow(display), width, height, depth);
XPutImage(display, p, DefaultGC(display, 0), img, 0, 0, 0, 0, width, height); // 0, 0, 0, 0 are src x,y and dst x,y
XEvent ev;
while (1) {
XNextEvent(display, &ev);
}
}
Update: It looks like I finally got answer: use GC associated with pixmap instead of DefaultGC (which has depth of root window)
#include <stdlib.h>
#include <X11/Xlib.h>
int main(int argc, char **argv)
{
int width = 100;
int height = 100;
int depth = 32; // works fine with depth = 24
int bitmap_pad = 32; // 32 for 24 and 32 bpp, 16, for 15&16
int bytes_per_line = 0; // number of bytes in the client image between the start of one scanline and the start of the next
Display *display=XOpenDisplay(0);
unsigned char *image32=(unsigned char *)malloc(width*height*4);
XImage *img = XCreateImage(display, CopyFromParent, depth, ZPixmap, 0, image32, width, height, bitmap_pad, bytes_per_line);
Pixmap p = XCreatePixmap(display, XDefaultRootWindow(display), width, height, depth);
XGCValues gcvalues;
GC gc = XCreateGC(display, p, 0, &gcvalues);
XPutImage(display, p, gc, img, 0, 0, 0, 0, width, height); // 0, 0, 0, 0 are src x,y and dst x,y
XEvent ev;
while (1) {
XNextEvent(display, &ev);
}
}
The problem is with DefaultGC() which return a GC with bit depth of system default screen. If you look at line 53 of your gist paste you see that this is 24:
depth of root window: 24 planes
On line 63 you see that it uses 0x22 as default which is shown in more detail in line 64 to 70:
visual:
visual id: 0x22
class: TrueColor
depth: 24 planes
available colormap entries: 256 per subfield
red, green, blue masks: 0xff0000, 0xff00, 0xff
significant bits in color specification: 8 bits
You could probably do this a bit nicer but as a start you can try this:
Note: This uses system visuals so most probably only support depth of 24 or 32.
#include <stdio.h>
#include <stdlib.h>
#include <X11/Xlib.h>
#include <X11/Xutil.h>
#ifdef DEBUG
int dbg = 1;
#else
int dbg = 0;
#endif
/* Return a GC based on depth */
int gc_depth(int depth, Display *dpy, Window scr, Window root, GC *gc)
{
Window win;
Visual *visual;
XVisualInfo vis_info;
XSetWindowAttributes win_attr;
unsigned long win_mask;
if(!XMatchVisualInfo(dpy, scr, depth, TrueColor, &vis_info)) {
fprintf(stderr,
" * ERR: %d depth not supported\n",
depth
);
return 1;
}
visual = vis_info.visual;
win_attr.colormap = XCreateColormap(dpy, root, visual, AllocNone);
win_attr.background_pixel = 0;
win_attr.border_pixel = 0;
win_mask = CWBackPixel | CWColormap | CWBorderPixel;
win = XCreateWindow(
dpy, root,
0, 0,
100, 100, /* dummy size */
0, depth,
InputOutput, visual,
win_mask, &win_attr);
/* To flush out any errors */
if (dbg) XSync(dpy, True);
*gc = XCreateGC(dpy, win, 0, 0);
if (dbg) XSync(dpy, True);
XDestroyWindow(dpy, win);
if (dbg) XSync(dpy, True);
return 0;
}
int main(void)
{
int w = 100;
int h = 100;
int depth = 32;
int bitmap_pad = 32;
int bpl = 0;
Display *dpy;
Window root;
Window scr;
GC gc;
int root_depth;
Pixmap pm;
XImage *img;
unsigned char *buf_img;
if(!(dpy = XOpenDisplay(NULL))) {
fprintf(stderr,
" * ERR: Failed to open display.\n");
return 1;
}
#ifdef DEBUG
/* To get errors in order, slows down
* One can also define int _Xdebug = 1;
* */
XSynchronize(dpy, True);
#endif
root = XDefaultRootWindow(dpy);
scr = XDefaultScreen(dpy);
if ((buf_img = malloc(w * h * 4)) == NULL) {
fprintf(stderr,
" * ERR: Unable to alloacte %d bytes\n",
w * h * 4);
return 1;
}
root_depth = DefaultDepth(dpy, scr);
fprintf(stderr,
"Default depth: %d\n",
root_depth);
/* This should be doen more nice */
if (depth != root_depth) {
if (gc_depth(depth, dpy, scr, root, &gc) != 0)
return 1;
} else {
gc = DefaultGC(dpy, 0);
}
img = XCreateImage(
dpy, CopyFromParent,
depth, ZPixmap,
0, (char *)buf_img,
w, h,
bitmap_pad, bpl);
/* To flush out any errors */
if (dbg) XSync(dpy, True);
pm = XCreatePixmap(
dpy, root,
w, h,
depth);
if (dbg) XSync(dpy, True);
XPutImage(
dpy, pm,
gc, img,
0, 0,
0, 0,
w, h);
if (dbg) XSync(dpy, True);
XFreePixmap(dpy, pm);
XDestroyImage(img);
XFreeGC(dpy, gc);
if (dbg) XSync(dpy, True);
fprintf(stderr,
"OK!\n");
return 0;
}
Well, your code works for 32 bits images if you just create a GC passing a drawable on argument which is 32 bits. XCreateGC(dpy, drawable, 0, 0), where drawable can be a pixmap with 32 bits depth. It works perfect with me.