Xlib: window is created in wrong position - c

I have simple xlib program which creates window. I think it has to show window on the upper-left corner of the screen because I pass 0, 0 to XCreateSimpleWindow function, but it's in upper-middle side. Why ?
#include <X11/Xlib.h>
#include <stdio.h>
#include <stdlib.h>
int
main(int argc, char* argv[])
{
Display* display;
int screen_num;
Window win;
unsigned int display_width,display_height;
unsigned int width, height;
char *display_name = getenv("DISPLAY");
display = XOpenDisplay(display_name);
screen_num = DefaultScreen(display);
display_width = DisplayWidth(display, screen_num);
display_height = DisplayHeight(display, screen_num);
width = (display_width / 3);
height = (display_height / 3);
win = XCreateSimpleWindow(display, RootWindow(display, screen_num), 0, 0, width, height, 1, BlackPixel(display, screen_num), WhitePixel(display, screen_num));
XMapWindow(display, win);
XSync(display, False);
while(1) { }
}

The top level windows are placed (and dimensioned) by the window manager which does whatever it suit it. Often the size is respected but the position not (in order to leave place for decoration, in order to respect placement policy of leaving toolbars clear, ...)
Try on a display without a window manager if you want your request to be respected (use VNC or similar to get such a display, don't try to use your desktop like this)

Related

override_redirect Xlib window attribute does nothing

I want to create a non-resizable window for my little game engine. I found out that override_redirect attribute set to true is exactly what I need. So I wrote my sample program:
#include <X11/Xlib.h>
#include <unistd.h>
Display *display;
Window window;
Visual *visual;
XSetWindowAttributes attributes;
int depth;
int screen;
int main(){
display = XOpenDisplay(NULL);
screen = DefaultScreen(display);
visual = DefaultVisual(display,screen);
depth = DefaultDepth(display,screen);
attributes.background_pixel = XWhitePixel(display,screen);
attributes.override_redirect = True;
window = XCreateWindow( display,XRootWindow(display,screen),
200, 200, 350, 200, 5, depth, InputOutput,
visual ,CWBackPixel, &attributes);
XSelectInput(display,window,ExposureMask | KeyPressMask) ;
XMapWindow(display, window);
XFlush(display);
sleep(10);
return 0;
}
However, my window is resizable and there is a title bar on the top of it. How can I get rid of those and why doesn't this code work as intended?
How can I get rid of those and why doesn't this code work as intended?
You forgot to set the CWOverrideRedirect bit in the bitmask:
CWBackPixel means that the background_pixel element in the attributes structure is considered.
You must use CWBackPixel|CWOverrideRedirect if both the elements background_pixel and override_redirect shall be considered:
attributes.background_pixel = XWhitePixel(display,screen);
attributes.override_redirect = True;
window = XCreateWindow( display,XRootWindow(display,screen),
200, 200, 350, 200, 5, depth, InputOutput,
visual, CWBackPixel|CWOverrideRedirect, &attributes);

Xlib + Unity Only close allowed action

I just want to make a sample app when the only possible action is close.
Is this possible with Unity(Ubuntu) ?
Do i make a mistake ?
#include <stdio.h>
#include <X11/Xlib.h>
#include <X11/Xos.h>
#include <X11/Xatom.h>
static void only_close(Display *display, Window window)
{
int retval;
Atom aa = XInternAtom(display, "_NET_WM_ALLOWED_ACTIONS", False);
Atom close = XInternAtom(display, " _NET_WM_ACTION_CLOSE", False);
retval = XChangeProperty(display, window, aa, XA_ATOM, 32, PropModeReplace, (unsigned char*)close, 1);
printf("###### XChangeProperty() reted %d\n", retval);
}
int main()
{
Display *dis;
Window win;
dis = XOpenDisplay(NULL);
win = XCreateSimpleWindow(dis, RootWindow(dis, 0), 1, 1, 500, 500, \
0, BlackPixel (dis, 0), BlackPixel(dis, 0));
XMapWindow(dis, win);
printf("window %i\n", (int)win);
only_close(dis, win);
XFlush(dis);
sleep(10);
return(0);
}
First, you need (unsigned char*)&close (an address of the data)
Second, you are setting the property too early, before WM has a chance to manage the window. A WM must discard the old value of this property when it first manages the window. Try after the first expose event, or just after a delay of 1 second.
Third, it is not guaranteed to work. On my machine (not Unity) the window actions in the taskbar are indeed disabled, but the window frame still has them the WM still allows them. I don't know if it's a bug in my WM or not.

Simple C Program that creates 2 X11 windows

I want to create 2 windows in linux that I'll later draw in from a separate thread. I currently have a non-deterministic bug where the second window that I create sometimes doesn't get created (no errors though).
Here is the code.
static void create_x_window(Display *display, Window *win, int width, int height)
{
int screen_num = DefaultScreen(display);
unsigned long background = WhitePixel(display, screen_num);
unsigned long border = BlackPixel(display, screen_num);
*win = XCreateSimpleWindow(display, DefaultRootWindow(display), /* display, parent */
0,0, /* x, y */
width, height, /* width, height */
2, border, /* border width & colour */
background); /* background colour */
XSelectInput(display, *win, ButtonPressMask|StructureNotifyMask);
XMapWindow(display, *win);
}
int main(void) {
XInitThreads(); // prevent threaded XIO errors
local_display = XOpenDisplay(":0.0");
Window self_win, remote_win;
XEvent self_event, remote_event;
create_x_window(local_display, &remote_win, 640,480);
// this line flushes buffer and blocks so that the window doesn't crash for a reason i dont know yet
XNextEvent(local_display, &remote_event);
create_x_window(local_display, &self_win, 320, 240);
// this line flushes buffer and blocks so that the window doesn't crash for a reason i dont know yet
XNextEvent(local_display, &self_event);
while (1) {
}
return 0;
}
I don't really care for capturing input in the windows, but I found a tutorial that had XSelectInput and XNextEvent (in an event loop) and I was having trouble making this work without either.
It's not a bug, it's a feature. You left out the event loop.
Although you cleverly called XNextEvent twice, the X protocol is asynchronous so the server may still be setting up the actual window while you call XNextEvent, so there is nothing to do.
Tutorial here.

Ncurses menu out of borders

I am trying to do simple menu, but I just can't get it to fit into box. Can you tell me what am I doing wrong?
// main
ITEM** items = // items initialization
WINDOW* menuWindow = create_newwin(itemsCount + 2, 38, 3, 5, true);
keypad(menuWindow, TRUE);
MENU* menu = create_menu(itemsCount, menuWindow, items, 2, 2, 5);
refresh();
post_menu(menu);
wrefresh(menuWindow);
// create win
WINDOW *create_newwin(const int height, const int width, const int starty, const int startx, const bool framed){
WINDOW *local_win = newwin(height, width, starty, startx);
if (framed) box(local_win, 0 , 0);
wrefresh(local_win);
return local_win;
}
//create menu
MENU* create_menu(const unsigned int count, WINDOW* window, ITEM** items, const unsigned int startx, const unsigned int starty, const unsigned int length){
MENU* local = new_menu((ITEM **)items);
menu_opts_off(local, O_ONEVALUE);
set_menu_win(local, window);
set_menu_sub(local, derwin(window, count + 2, length, startx, starty));
set_menu_format(local, count, 1);
set_menu_mark(local, " ");
return local;
}
This is how my menu looks like:
It would probably be helpful if you'd post the actual code that gives you the result in the screencap, because I can't reproduce it.
I do see a couple problems here, though. First, this line:
set_menu_sub(local, derwin(window, count + 2, length, startx, starty));
Notice the count + 2 attempts to make a subwindow with height greater than its parent. According to the curs_window(3X) man page, derwin():
returns an error if the parent window pointer is null, or if any of its ordinates or dimensions is negative, or if the resulting window does not fit inside the parent window.
It's worth noting that on my machine, derwin() returns NULL on failure and doesn't set errno, so the documentation isn't necessarily all there.
The other thing that looks strange is this:
MENU* menu = create_menu(itemsCount, menuWindow, items, 2, 2, 5);
Curses windows are 0-addressed from their origin, so with the rest of your code, that's going to attempt to put your menu at {2,2} of the menuWindow. That is, even if you fix the above, it's still going to write over the bottom border of your box with the last menu entry. What's more, your last parameter being 5 means your menu is only going to have five columns including the menu_mark string.
For further reading, I would encourage you to look at the documentation for menu.h because they cover nearly this exact scenario.
You need to create a subwindow for the menu. So you can move it around in the parent-window.

How to draw directly on the desktop?

I'm wondering how to draw directly on the root window in an X11 environment with Cairo (in C), in order to make widgets. I've copied some parts of the code of tint2, but it's quite enormous, and the only result I have is not satisfying.
I would be pleased to have a complete working sample code, or at least some tips or little programs to study.
Thank you guys !
The "bottom" window is the root window. The problem is that in some desktop environments we have windows on top of the root window, so if you change the root window, you won't see your changes: you need to change the window that's on the top.
This program does what you ask for: draw on the root window. To test it, I suggest you to:
ctrl+alt+f1
login as root
stop your desktop environment ("/etc/init.d/gdm stop", "/etc/init.d/kdm stop" or whatever is needed in your distro)
X -noreset -retro &
DISPLAY=:0.0 xterm &
DISPLAY=:0.0 metacity &
Then, go back to X (ctrl+alt+f7 or maybe f8) and run the program.
If you want to draw on Nautilus' top window, you will need to find out its window ID and then use it as the "w" variable. The "xwininfo" command might help you testing...
#include <assert.h>
#include <stdio.h>
#include <X11/Xlib.h>
#include <cairo.h>
#include <cairo-xlib.h>
int width, height;
void draw(cairo_t *cr) {
int quarter_w = width / 4;
int quarter_h = height / 4;
cairo_set_source_rgb(cr, 1.0, 0.0, 0.0);
cairo_rectangle(cr, quarter_w, quarter_h, quarter_w * 2, quarter_h * 2);
cairo_fill(cr);
}
int main() {
Display *d = XOpenDisplay(NULL);
assert(d);
int s = DefaultScreen(d);
Window w = RootWindow(d, s);
width = DisplayWidth(d, s);
height = DisplayHeight(d, s);
cairo_surface_t *surf = cairo_xlib_surface_create(d, w,
DefaultVisual(d, s),
width, height);
cairo_t *cr = cairo_create(surf);
XSelectInput(d, w, ExposureMask);
draw(cr);
XEvent ev;
while (1) {
XNextEvent(d, &ev);
printf("Event!\n");
if (ev.type == Expose) {
draw(cr);
}
}
cairo_destroy(cr);
cairo_surface_destroy(surf);
XCloseDisplay(d);
return 0;
}

Resources