libX11: XPutImage first call - c

I've created XImage using XCreateImage and use XPutImage to display it on window, but XPutImage shows this picture only on second call of it. Why this happens?
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <X11/Xlib.h>
#include <X11/Xutil.h>
void draw(char *rgb_out, int w, int h)
{
int i = 0;
for (i = 0;i < w*h;i += 4) {
rgb_out[i + 1] = 0;
rgb_out[i + 2] = 0;
rgb_out[i + 3] = 0;
}
return;
}
XImage *create_ximage(Display *display, Visual *visual, int width, int height)
{
char *image32 = (char *)malloc(width * height * 4);
draw(image32, width, height);
return XCreateImage(display, visual, 24,
ZPixmap, 0, image32,
width, height, 32, 0);
}
int main(int argc, char **argv)
{
int win_b_color;
int win_w_color;
XEvent xev;
Window window;
GC gc;
Display *display = XOpenDisplay(NULL);
Visual *visual;
XImage *ximage;
win_b_color = BlackPixel(display, DefaultScreen(display));
win_w_color = BlackPixel(display, DefaultScreen(display));
window = XCreateSimpleWindow(display,
DefaultRootWindow(display),
0, 0, 600, 400, 0,
win_b_color, win_w_color);
gc = XCreateGC(display, window, 0, NULL);
visual = DefaultVisual(display, 0);
XMapWindow(display, window);
XFlush(display);
ximage = create_ximage(display, visual, 100, 100);
while (1) {
int r;
r = XPutImage(display, window,
gc, ximage, 0, 0, 0, 0,
100, 100);
printf("RES: %i\n", r);
XSync(display, 1);
XFlush(display);
getchar();
}
return 0;
}

The trick is to wait that the windows is mapped. You can do this by Expose event.
int main(int argc, char **argv)
{
int win_b_color;
int win_w_color;
XEvent xev;
Window window;
GC gc;
Display *display = XOpenDisplay(NULL);
Visual *visual;
XImage *ximage;
win_b_color = BlackPixel(display, DefaultScreen(display));
win_w_color = BlackPixel(display, DefaultScreen(display));
window = XCreateSimpleWindow(display,
DefaultRootWindow(display),
0, 0, 600, 400, 0,
win_b_color, win_w_color);
visual = DefaultVisual(display, 0);
XSelectInput(display, window, ExposureMask | KeyPressMask);
XMapWindow(display, window);
XFlush(display);
gc = XCreateGC(display, window, 0, NULL);
ximage = create_ximage(display, visual, 100, 100);
XEvent event;
bool exit = false;
while (!exit) {
int r;
XNextEvent(display, &event);
if (event.type == Expose)
{
r = XPutImage(display, window,
gc, ximage, 0, 0, 0, 0,
100, 100);
printf("RES: %i\n", r);
}
else if (event.type == KeyPress)
exit = true;
}
return 0;
}

Related

Cannot get SDL_SetTextureColorMod to work

I am trying to change the color of the image displayed. The image contains characters in black and I want to display them in red. So I am trying to use SDL_SetTextureColorMod but it seems I am doing it wrong since the image rendered is still black. Does someone see the problem with my code?
#include "SDL.h"
#include <stdio.h>
int main(int argc, char **argv) {
SDL_Init(SDL_INIT_VIDEO);
SDL_Window *window;
SDL_Renderer *renderer;
SDL_CreateWindowAndRenderer(640, 480, 0, &window, &renderer);
SDL_Surface *surface = SDL_LoadBMP("font.bmp");
SDL_Texture *texture = SDL_CreateTextureFromSurface(renderer, surface);
SDL_FreeSurface(surface);
int keep_going = 1;
while (keep_going) {
SDL_Event e;
while (SDL_PollEvent(&e)) {
if (e.type == SDL_QUIT) {
keep_going = 0;
}
}
SDL_SetRenderDrawColor(renderer, 255, 255, 255, 255);
SDL_RenderClear(renderer);
int ret = SDL_SetTextureColorMod(texture, 255, 0, 0);
if(ret != 0){
printf("%s",SDL_GetError());
}
SDL_RenderCopy(renderer, texture, NULL, NULL);
SDL_RenderPresent(renderer);
}
SDL_Quit();
return 0;
}
The image I'm using:

flickering in allegro with loops

The red bars a cross the top flickers. I can make them out of the loop but not in the loop.
#include <allegro.h>
void init();
void deinit();
int main() {
init();
int length = 20;
int x= 900;
int y= 600;
int c;
//while (!key[KEY_ESC]) {
c = makecol(0, 0, 0);
rectfill (screen, 0, 0, 900, 400, c);
c = makecol(0, 200, 0);
rectfill (screen, 0, 0, 900, 400, c);// curb
for (int i =0; i=10; i++){
int bar=0;
c = makecol(200, 0, 0);
rectfill (screen, bar, 0, x+80, 40, c);
c = makecol(0, 0, 0);
rectfill (screen, bar+80, 0, x+100, 40, c);
bar+=100;
}
deinit();
return 0;
}
END_OF_MAIN()
void init() {
int depth, res;
allegro_init();
depth = desktop_color_depth();
if (depth == 0) depth = 32;
set_color_depth(depth);
res = set_gfx_mode(GFX_AUTODETECT_WINDOWED, 900, 600, 0,0);
if (res != 0) {
allegro_message(allegro_error);
exit(-1);
}
install_timer();
install_keyboard();
install_mouse();
/* add other initializations here */
}
void deinit() {
clear_keybuf();
/* add other deinitializations here */
}
So what why does it flicker and how do I stop that. I have had
issue with for loops before do they just not work whit allegro?
or am I being dumb and just written something wrong?

Setting X11 root window pixmap

The code below is supposed to make root window white, but does nothing. Compiles and runs with no errors. I omitted only includes and variable definitions.
int
main(int argc, char **argv) {
dpy = XOpenDisplay(NULL);
if (!dpy) {
fputs("cannot open display\n", stderr);
return EXIT_FAILURE;
}
screen = DefaultScreen(dpy);
root = RootWindow(dpy, screen);
vis = DefaultVisual(dpy, screen);
depth = DefaultDepth(dpy, screen);
height = DisplayHeight(dpy, screen);
width = DisplayWidth(dpy, screen);
img = malloc(depth/8 * height * width);
if (img == NULL) {
perror("malloc() failed");
return EXIT_FAILURE;
}
memset(img, 0xFF, depth/8 * height * width);
ximg = XCreateImage(dpy, vis, depth, ZPixmap, 0, img, width, height, 32, 0);
pm = XCreatePixmap(dpy, root, width, height, depth);
gc = XCreateGC(dpy, pm, 0, NULL);
XPutImage(dpy, pm, gc, ximg, 0, 0, 0, 0, width, height);
XSetWindowBackgroundPixmap(dpy, root, pm);
XClearWindow(dpy, root);
XFlush(dpy);
XDestroyImage(ximg);
XFreePixmap(dpy, pm);
XFreeGC(dpy, gc);
XCloseDisplay(dpy);
return EXIT_SUCCESS;
}
How do I even start troubleshooting this? removing XClearWindow(dpy, root); does not help.
Apparently XSetWindowBackgroundPixmap() needs some prior atom setup. This borrowed function fixed the issue.
// Adapted from fluxbox' bsetroot
int
setRootAtoms(Pixmap pixmap)
{
Atom atom_root, atom_eroot, type;
unsigned char *data_root, *data_eroot;
int format;
unsigned long length, after;
atom_root = XInternAtom(display, "_XROOTMAP_ID", True);
atom_eroot = XInternAtom(display, "ESETROOT_PMAP_ID", True);
// doing this to clean up after old background
if (atom_root != None && atom_eroot != None) {
XGetWindowProperty(display, RootWindow(display, screen), atom_root, 0L, 1L, False, AnyPropertyType, &type, &format, &length, &after, &data_root);
if (type == XA_PIXMAP) {
XGetWindowProperty(display, RootWindow(display, screen), atom_eroot, 0L, 1L, False, AnyPropertyType, &type, &format, &length, &after, &data_eroot);
if (data_root && data_eroot && type == XA_PIXMAP && *((Pixmap *) data_root) == *((Pixmap *) data_eroot))
XKillClient(display, *((Pixmap *) data_root));
}
}
atom_root = XInternAtom(display, "_XROOTPMAP_ID", False);
atom_eroot = XInternAtom(display, "ESETROOT_PMAP_ID", False);
if (atom_root == None || atom_eroot == None)
return 0;
// setting new background atoms
XChangeProperty(display, RootWindow(display, screen), atom_root, XA_PIXMAP, 32, PropModeReplace, (unsigned char *) &pixmap, 1);
XChangeProperty(display, RootWindow(display, screen), atom_eroot, XA_PIXMAP, 32, PropModeReplace, (unsigned char *) &pixmap, 1);
return 1;
}

Draw border (frame) using xlib

Is it possible to draw transparent window without title bar, close button, responses on mouse buttons using xlib. So just border with specific color and width? Something like
this orange rectangle is what I need to create. Also I'd like to have possibility to move, resize, close and make it flicking (change border's color on timer) programatically.
I managed to create transparent window without titlebar and draw rectangles on each side of the window to make border-effect:
#define W_WIDTH 640
#define W_HEIGHT 480
#define X_POS 100
#define Y_POS 120
#define BORDER_WIDTH 2
Display *dpy;
Window w;
XRectangle rectangles[4] =
{
{ X_POS, Y_POS, W_WIDTH, BORDER_WIDTH },
{ X_POS, Y_POS, BORDER_WIDTH, W_HEIGHT },
{ X_POS, W_HEIGHT - BORDER_WIDTH, W_WIDTH, BORDER_WIDTH },
{ W_WIDTH - BORDER_WIDTH, Y_POS, BORDER_WIDTH, W_HEIGHT }
};
int main(int argc, char *argv[])
{
GC gc;
XGCValues gcv;
int run = 1;
dpy = XOpenDisplay(NULL);
XVisualInfo vinfo;
XMatchVisualInfo(dpy, DefaultScreen(dpy), 32, TrueColor, &vinfo);
XSetWindowAttributes attr;
attr.colormap = XCreateColormap(dpy, DefaultRootWindow(dpy), vinfo.visual, AllocNone);
w = XCreateWindow(dpy, DefaultRootWindow(dpy), X_POS, Y_POS,
W_WIDTH, W_HEIGHT, BORDER_WIDTH, vinfo.depth,
InputOutput, vinfo.visual, CWColormap | CWBorderPixel | CWBackPixel, &attr);
XColor color;
Colormap colormap;
char orangeDark[] = "#FF8000";
colormap = DefaultColormap(dpy, 0);
XParseColor(dpy, colormap, orangeDark, &color);
XAllocColor(dpy, colormap, &color);
gcv.line_width = BORDER_WIDTH;
gc = XCreateGC(dpy, w, GCLineWidth, &gcv);
XSelectInput(dpy, w, ExposureMask);
Atom window_type = XInternAtom(dpy, "_NET_WM_WINDOW_TYPE", False);
long value = XInternAtom(dpy, "_NET_WM_WINDOW_TYPE_DOCK", False);
XChangeProperty(dpy, w, window_type, XA_ATOM, 32, PropModeReplace, (unsigned char *) &value, 1);
XMapWindow(dpy, w);
XSync(dpy, False);
while(run)
{
XEvent xe;
XNextEvent(dpy, &xe);
switch (xe.type)
{
case Expose:
XSetForeground(dpy, gc, color.pixel);
XDrawRectangles(dpy, w, gc, rectangles, 4);
XFillRectangles(dpy, w, gc, rectangles, 4);
XSync(dpy, False);
break;
default:
break;
}
}
XDestroyWindow(dpy, w);
XCloseDisplay(dpy);
return 0;
}
This code works almost fine except the thing, that my orange border is semitransparent and is almost invisible on light windows:
Could you please tell how I need change my code to draw solid orange rectangles? Another variant I have is to draw transparent rectangle inside of orange window. But I didn't find any info in the Internet about how to do that.
Two main mistakes.
Not initializing attr and gcv to 0
Not using attr.colormap for color allocation
That should help:
#include <X11/Xlib.h>
#include <X11/Xutil.h>
#include <X11/Xatom.h>
#define W_WIDTH 640
#define W_HEIGHT 480
#define X_POS 100
#define Y_POS 120
#define BORDER_WIDTH 2
int main(int argc, char *argv[]) {
XRectangle rectangles[4] = {
{ X_POS, Y_POS, W_WIDTH, BORDER_WIDTH },
{ X_POS, Y_POS, BORDER_WIDTH, W_HEIGHT },
{ X_POS, W_HEIGHT - BORDER_WIDTH, W_WIDTH, BORDER_WIDTH },
{ W_WIDTH - BORDER_WIDTH, Y_POS, BORDER_WIDTH, W_HEIGHT }
};
Display *dpy = XOpenDisplay(NULL);
XSetWindowAttributes attr = {0};
XGCValues gcv = {0};
XVisualInfo vinfo;
GC gc;
Window w;
int run = 1;
XMatchVisualInfo(dpy, DefaultScreen(dpy), 32, TrueColor, &vinfo);
attr.colormap = XCreateColormap(dpy, DefaultRootWindow(dpy), vinfo.visual, AllocNone);
XColor color;
char orangeDark[] = "#FF8000";
XParseColor(dpy, attr.colormap, orangeDark, &color);
XAllocColor(dpy, attr.colormap, &color);
w = XCreateWindow(dpy, DefaultRootWindow(dpy), X_POS, Y_POS,
W_WIDTH, W_HEIGHT, BORDER_WIDTH, vinfo.depth,
InputOutput, vinfo.visual, CWColormap | CWBorderPixel | CWBackPixel, &attr);
gcv.line_width = BORDER_WIDTH;
gc = XCreateGC(dpy, w, GCLineWidth, &gcv);
XSelectInput(dpy, w, ExposureMask);
long value = XInternAtom(dpy, "_NET_WM_WINDOW_TYPE_DOCK", False);
XChangeProperty(dpy, w, XInternAtom(dpy, "_NET_WM_WINDOW_TYPE", False),
XA_ATOM, 32, PropModeReplace, (unsigned char *) &value, 1);
XMapWindow(dpy, w);
XSync(dpy, False);
while(run) {
XEvent xe;
XNextEvent(dpy, &xe);
switch (xe.type) {
case Expose:
XSetForeground(dpy, gc, color.pixel);
XDrawRectangles(dpy, w, gc, rectangles, 4);
XFillRectangles(dpy, w, gc, rectangles, 4);
XSync(dpy, False);
break;
default:
break;
}
}
XDestroyWindow(dpy, w);
XCloseDisplay(dpy);
return 0;
}
Result:

X11 XImage manipulation

I'm trying to pick up an image from my brand new window and then draw it back to the same window, just to train on XLib.
Here is my code :
#include<stdio.h>
#include<stdlib.h>
#include<stdint.h>
#include<X11/Xlib.h>
#include<X11/Xutil.h>
#include<sys/stat.h>
#include<sys/time.h>
#include<sys/types.h>
#include<unistd.h>
int main(int argc, char *argv[]) {
fd_set eventset;
fd_set zeroset;
// struct timeval timeout = {0, 0};
Display *display = 0;
int screen;
Window wnd;
XVisualInfo vinfo;
XSetWindowAttributes attr;
XEvent event;
XImage *bg;
Atom WM_message[2];
int run = 1;
FD_ZERO(&eventset);
FD_ZERO(&zeroset);
if(!(display = XOpenDisplay(0))) {
/* Display not found */
printf("Fail display.\n");
return 0;
}
screen = XDefaultScreen(display);
if(!XMatchVisualInfo(display, screen, 32, TrueColor, &vinfo)) {
if(!XMatchVisualInfo(display, screen, 24, TrueColor, &vinfo)) {
/* No proper color depth available */
XCloseDisplay(display); /* Close X communication */
printf("No found color display. Sorry.\n");
return 0;
}
}
attr.colormap = XCreateColormap(display, DefaultRootWindow(display), vinfo.visual, AllocNone);
attr.border_pixel = 0;
attr.background_pixel = 0x80000000;
attr.bit_gravity = NorthWestGravity;
attr.win_gravity = NorthWestGravity;
wnd = XCreateWindow(display, DefaultRootWindow(display), 0, 0, 300, 300, 0,
vinfo.depth, InputOutput, vinfo.visual,
CWColormap | CWBorderPixel | CWBackPixel | CWBitGravity | CWWinGravity, &attr);
/* Subscribe to window closing event */
WM_message[0] = XInternAtom(display, "WM_PROTOCOLS", 1);
WM_message[1] = XInternAtom(display, "WM_DELETE_WINDOW", 1);
XSetWMProtocols(display, wnd, WM_message, 2);
XFreeColormap(display, attr.colormap);
XSelectInput(display, wnd, ExposureMask | ButtonPressMask | KeyPressMask);
XMapWindow(display, wnd);
bg = XGetImage(display, XDefaultRootWindow(display), 0, 0, 300, 300, AllPlanes, ZPixmap);
// bg = XGetImage(display, wnd, 100, 100, 100, 100, AllPlanes, ZPixmap);
/* int x;
for(x = 0; x < 10000; x++) {
bg->data[x] = 0x80;
} */
XPutImage(display, wnd, XDefaultGC(display, screen), bg, 0, 0, 0, 0, 300, 300);
// XPutImage(display, wnd, XDefaultGC(display, screen), bg, 100, 100, 100, 100, 100, 100);
XMapWindow(display, wnd);
XFlush(display);
while(run) {
XNextEvent(display, &event);
switch(event.type) {
case Expose:
printf("w = %d, h = %d\n", event.xexpose.width, event.xexpose.height);
break;
case DestroyNotify:
run = 0;
break;
case ClientMessage:
{
if(event.xclient.message_type == WM_message[0]) {
if(event.xclient.data.l[0] == WM_message[1]) {
run = 0;
}
}
}
default:;
}
}
XDestroyImage(bg);
XDestroyWindow(display, wnd);
XCloseDisplay(display);
return 0;
}
This crash my program either on porteus and mobaxterm.
But this lines:
// bg = XGetImage(display, wnd, 100, 100, 100, 100, AllPlanes, ZPixmap);
/* int x;
for(x = 0; x < 10000; x++) {
bg->data[x] = 0x80;
} */
// XPutImage(display, wnd, XDefaultGC(display, screen), bg, 100, 100, 100, 100, 100, 100);
Doesn't crash my program... it just render nothing.
Can someone help me understand why do I experiment this weird behavior of X?
This is the error message I am getting:
X Error of failed request: BadMatch (invalid parameter attributes)
Major opcode of failed request: 72 (X_PutImage) Serial number of
failed request: 16 Current serial number in output stream: 18
After further reasearches and tries, I finnally found 2 facts :
First my post is mistaken :
this doesn't crash :
XPutImage(display, XDefaultRootWindow(display), XDefaultGC(display, screen), bg, 100, 100, 100, 100, 100, 100);
Those lines crash :
XPutImage(display, wnd, XDefaultGC(display, screen), bg, 0, 0, 0, 0, 300, 300);
XPutImage(display, wnd, XDefaultGC(display, screen), bg, 100, 100, 100, 100, 100, 100);
Second :
Writing on root window with default gc is alright because default gc is a gc corresponding to the default root window.
But using this GC for my own window is an error since I used color depth that can differ from root window.
So I have now this running well:
#include<stdio.h>
#include<stdlib.h>
#include<stdint.h>
#include<X11/Xlib.h>
#include<X11/Xutil.h>
#include<sys/stat.h>
#include<sys/time.h>
#include<sys/types.h>
#include<unistd.h>
int main(int argc, char *argv[]) {
fd_set eventset;
fd_set zeroset;
// struct timeval timeout = {0, 0};
Display *display = 0;
int screen;
Window wnd;
XVisualInfo vinfo;
XSetWindowAttributes attr;
XEvent event;
XImage *bg;
GC mainGC;
Atom WM_message[2];
int run = 1;
FD_ZERO(&eventset);
FD_ZERO(&zeroset);
if(!(display = XOpenDisplay(0))) {
/* Display not found */
printf("Fail display.\n");
return 0;
}
screen = XDefaultScreen(display);
if(!XMatchVisualInfo(display, screen, 32, TrueColor, &vinfo)) {
if(!XMatchVisualInfo(display, screen, 24, TrueColor, &vinfo)) {
/* No proper color depth available */
XCloseDisplay(display); /* Close X communication */
printf("No found color display. Sorry.\n");
return 0;
}
}
attr.colormap = XCreateColormap(display, DefaultRootWindow(display), vinfo.visual, AllocNone);
attr.border_pixel = 0;
attr.background_pixel = 0x80000000;
attr.bit_gravity = NorthWestGravity;
attr.win_gravity = NorthWestGravity;
wnd = XCreateWindow(display, DefaultRootWindow(display), 0, 0, 300, 300, 0,
vinfo.depth, InputOutput, vinfo.visual,
CWColormap | CWBorderPixel | CWBackPixel | CWBitGravity | CWWinGravity, &attr);
/* Subscribe to window closing event */
WM_message[0] = XInternAtom(display, "WM_PROTOCOLS", 1);
WM_message[1] = XInternAtom(display, "WM_DELETE_WINDOW", 1);
XSetWMProtocols(display, wnd, WM_message, 2);
XFreeColormap(display, attr.colormap);
XSelectInput(display, wnd, ExposureMask | ButtonPressMask | KeyPressMask);
XMapWindow(display, wnd);
XFlush(display);
mainGC = XCreateGC(display, wnd, 0, 0);
bg = XGetImage(display, wnd, 0, 0, 100, 100, AllPlanes, ZPixmap);
int x;
for(x = 0; x < 10000; x++) {
bg->data[x] = 0x80;
}
XPutImage(display, wnd, mainGC, bg, 0, 0, 100, 100, 100, 100);
while(run) {
XNextEvent(display, &event);
switch(event.type) {
case Expose:
printf("w = %d, h = %d\n", event.xexpose.width, event.xexpose.height);
break;
case DestroyNotify:
run = 0;
break;
case ClientMessage:
{
if(event.xclient.message_type == WM_message[0]) {
if(event.xclient.data.l[0] == WM_message[1]) {
run = 0;
}
}
}
default:;
}
}
XDestroyImage(bg);
XDestroyWindow(display, wnd);
XCloseDisplay(display);
return 0;
}

Resources