Sign in to follow this  
CoffeeMug

Xlib is... interesting

Recommended Posts

[rant] I always thought that a *good* API lets you initialize and use it with very few lines of code by using reasonable "least surprise" defaults, but gives you as much power as possible by letting you customize those defaults if you want them. I always thought Win32 API did a pretty bad job at this. In particular, creating a window requires one to type quite a bit of code. I never understood why they couldn't just let us do this:
HWND wnd = CreateWindow(WndProc);
ShowWindow(wnd);
If someone wanted to customize the location, size, etc. one could do this:
HWND wnd = CreateWindow(WndProc);
SetWindowPos(wnd, 100, 100);
SetWindowSize(wnd 200, 200);
ShowWindow(wnd);
Yesterday I was introduced to Xlib. If you buy the idea that the above principle defines (or at least describes) good APIs, this is probably the crappiest thing I've seen in my entire programming career. I understand that they had existing X protocol to deal with but why did they decide that making the client take *soooo* many explicit steps to open a window is a good idea? At the beginning of the project I decided to use as few API wrappers as possible mainly because I'd like to learn the details of *nix development but now I am pretty tempted to drop Xlib and go with a wrapper. I know that writing a reasonably simple window wrapper is not that much work and I'll do it and forget about it in a few days but the process of getting through the (IMO unreasonable) entry level complexity of Xlib is a pain in the neck. The fact that there is no really good documentation for it adds up to the frustration. Does anyone else have... experiences [smile] with Xlib? [/rant]

Share this post


Link to post
Share on other sites
To be brutally honest, I have no idea what this even is. I assume it's an API, and it's called Xlib, and it takes unbelievable amounts of code to create a window (as with Win32). I've not, however, seen any such proof of this "code", and I refuse to believe that it's more than a small amount without sources or examples.

I award you no points, and may God have mercy on my rating.

Share this post


Link to post
Share on other sites
Quote:
Original post by Boku San
To be brutally honest, I have no idea what this even is.

It's a unix GUI API that wraps X protocol.
Quote:
Original post by Boku San
I've not, however, seen any such proof of this "code", and I refuse to believe that it's more than a small amount without sources or examples.

I'll be happy to provide you with one. Here's a piece of code straight from NeHe's tutorial. Note, I am not posting *everything* necessary to create a window, just the creation code. You'd still need to create a message loop.

XVisualInfo *vi;
Colormap cmap;
int dpyWidth, dpyHeight;
int i;
int glxMajorVersion, glxMinorVersion;
int vidModeMajorVersion, vidModeMinorVersion;
XF86VidModeModeInfo **modes;
int modeNum;
int bestMode;
Atom wmDelete;
Window winDummy;
unsigned int borderDummy;

GLWin.fs = fullscreenflag;
/* set best mode to current */
bestMode = 0;
/* get a connection */
GLWin.dpy = XOpenDisplay(0);
GLWin.screen = DefaultScreen(GLWin.dpy);
XF86VidModeQueryVersion(GLWin.dpy, &vidModeMajorVersion,
&vidModeMinorVersion);
printf("XF86VidModeExtension-Version %d.%d\n", vidModeMajorVersion,
vidModeMinorVersion);
XF86VidModeGetAllModeLines(GLWin.dpy, GLWin.screen, &modeNum, &modes);
/* save desktop-resolution before switching modes */
GLWin.deskMode = *modes[0];
/* look for mode with requested resolution */
for (i = 0; i < modeNum; i++)
{
if ((modes[i]->hdisplay == width) && (modes[i]->vdisplay == height))
{
bestMode = i;
}
}
/* get an appropriate visual */
vi = glXChooseVisual(GLWin.dpy, GLWin.screen, attrListDbl);
if (vi == NULL)
{
vi = glXChooseVisual(GLWin.dpy, GLWin.screen, attrListSgl);
GLWin.doubleBuffered = False;
printf("Only Singlebuffered Visual!\n");
}
else
{
GLWin.doubleBuffered = True;
printf("Got Doublebuffered Visual!\n");
}
glXQueryVersion(GLWin.dpy, &glxMajorVersion, &glxMinorVersion);
printf("glX-Version %d.%d\n", glxMajorVersion, glxMinorVersion);
/* create a GLX context */
GLWin.ctx = glXCreateContext(GLWin.dpy, vi, 0, GL_TRUE);
/* create a color map */
cmap = XCreateColormap(GLWin.dpy, RootWindow(GLWin.dpy, vi->screen),
vi->visual, AllocNone);
GLWin.attr.colormap = cmap;
GLWin.attr.border_pixel = 0;

if (GLWin.fs)
{
XF86VidModeSwitchToMode(GLWin.dpy, GLWin.screen, modes[bestMode]);
XF86VidModeSetViewPort(GLWin.dpy, GLWin.screen, 0, 0);
dpyWidth = modes[bestMode]->hdisplay;
dpyHeight = modes[bestMode]->vdisplay;
printf("Resolution %dx%d\n", dpyWidth, dpyHeight);
XFree(modes);

/* create a fullscreen window */
GLWin.attr.override_redirect = True;
GLWin.attr.event_mask = ExposureMask | KeyPressMask | ButtonPressMask |
StructureNotifyMask;
GLWin.win = XCreateWindow(GLWin.dpy, RootWindow(GLWin.dpy, vi->screen),
0, 0, dpyWidth, dpyHeight, 0, vi->depth, InputOutput, vi->visual,
CWBorderPixel | CWColormap | CWEventMask | CWOverrideRedirect,
&GLWin.attr);
XWarpPointer(GLWin.dpy, None, GLWin.win, 0, 0, 0, 0, 0, 0);
XMapRaised(GLWin.dpy, GLWin.win);
XGrabKeyboard(GLWin.dpy, GLWin.win, True, GrabModeAsync,
GrabModeAsync, CurrentTime);
XGrabPointer(GLWin.dpy, GLWin.win, True, ButtonPressMask,
GrabModeAsync, GrabModeAsync, GLWin.win, None, CurrentTime);
}
else
{
/* create a window in window mode*/
GLWin.attr.event_mask = ExposureMask | KeyPressMask | ButtonPressMask |
StructureNotifyMask;
GLWin.win = XCreateWindow(GLWin.dpy, RootWindow(GLWin.dpy, vi->screen),
0, 0, width, height, 0, vi->depth, InputOutput, vi->visual,
CWBorderPixel | CWColormap | CWEventMask, &GLWin.attr);
/* only set window title and handle wm_delete_events if in windowed mode */
wmDelete = XInternAtom(GLWin.dpy, "WM_DELETE_WINDOW", True);
XSetWMProtocols(GLWin.dpy, GLWin.win, &wmDelete, 1);
XSetStandardProperties(GLWin.dpy, GLWin.win, title,
title, None, NULL, 0, NULL);
XMapRaised(GLWin.dpy, GLWin.win);
}
/* connect the glx-context to the window */
glXMakeCurrent(GLWin.dpy, GLWin.win, GLWin.ctx);
XGetGeometry(GLWin.dpy, GLWin.win, &winDummy, &GLWin.x, &GLWin.y,
&GLWin.width, &GLWin.height, &borderDummy, &GLWin.depth);
printf("Depth %d\n", GLWin.depth);
if (glXIsDirect(GLWin.dpy, GLWin.ctx))
printf("Congrats, you have Direct Rendering!\n");
else
printf("Sorry, no Direct Rendering possible!\n");
initGL();
return True;


I know there's some graphics specific code in there but even if you take that out, the effort required to create a window is way above what it should be.

Share this post


Link to post
Share on other sites
*squeak*.

*many gestures of confusion, that also convey a subtle sense of approval*

*grabs a pen and writes rating++ onto a sign*

Share this post


Link to post
Share on other sites
about Xlib, it really was not designed to be used directtly... its menatality is the one uses a toolkit, i.e. a wrapper... some folks complain (and with justification) that the wappers/toolkits introduce executabel code bloat... on the other had using Xlib directly introduces huge source code bloat(sigh) at any rate if you just need soemthing quick and dirty I recommnet fltk,
the webpage is:

www.fltk.org

it is not perfect, but is not so painful to use(if you like C++)
Another nice beinifit is that it is on MaxOS and Win32 too, so it could be nice... the documentatio is not super useful but poking around it is a good way to start.
There are some straight C toolkits... though when I was learning X, I used Xview ... boy that sucked.... all the functions used the variable arguments prototypes so if you messed up in passing parameters you found out at runtime... and sometimes there were too many paramters... oh how I did not like xView (sorry for mentioning it now)
At any rate, just to repeat, Xlib really was not meant to be used directly, but was meant so that toolkits were built on top of it... also it has the whole run a progam on one computer display on another mentality too....

Share this post


Link to post
Share on other sites
Thanks for the link, I'll take a look. I'm really doing something very simple: creating a single class to wrap the main game window. I was reluctant to use any toolkits because I don't feel that introducing such dependancies is necessary: I'll just create my class and forget about it once and for all. In any case, I'll evaluate fltk, who knows, may be I'll end up using it. I feel bad for people who implement toolkits like GTK and Qt and have to work with Xlib on daily basis.

Share this post


Link to post
Share on other sites
GTK doesn't even use Xlib directly, it uses GDK, which is a very thin xlib wrapper.

You've got a few options:

gtk or qt: everybody has them, so its not like you're introducing a ridiculous dependancy. Furthermore, if you use pure gtk/qt and not gnome/kde startup times are still fast, whether the library is in memory already or not.

fltk or others: nobody has them. People would have to install them to play your game (or whatnot), but they might have a smaller memory footprint than gtk/qt

xcb: supposedly a BETTER wrapper for the X protocol. Toolkits are considering rewriting to xcb so that xlib can die forever. (it's ugly for more reasons than you know!)

ummm.... SDL: all linux gamers already have it installed. Pretty simple. Pretty lightweight and small, too.

Share this post


Link to post
Share on other sites
Quote:
Original post by CoffeeMug
Quote:
Original post by Boku San
To be brutally honest, I have no idea what this even is.

It's a unix GUI API that wraps X protocol.
Quote:
Original post by Boku San
I've not, however, seen any such proof of this "code", and I refuse to believe that it's more than a small amount without sources or examples.

I'll be happy to provide you with one. Here's a piece of code straight from NeHe's tutorial. Note, I am not posting *everything* necessary to create a window, just the creation code. You'd still need to create a message loop.
*** Source Snippet Removed ***
I know there's some graphics specific code in there but even if you take that out, the effort required to create a window is way above what it should be.


#include <X11/Xlib.h>
#include <unistd.h>

int main ()
{
Display *display = XOpenDisplay(0);
if (!display)
throw "Can't connect to X server";
// After this point, Xlib will report errors for us.
int screen = DefaultScreen(display);
Window window = XCreateSimpleWindow(display, RootWindow(display, screen), 0, 0, 640, 480, 0, 0, 0);
XMapWindow(display, window);
XSync(display, False);
sleep(4);
XCloseDisplay(display);
}

Doesn't seem that difficult.

Share this post


Link to post
Share on other sites
Quote:
Original post by CoffeeMug
I'll be happy to provide you with one. Here's a piece of code straight from NeHe's tutorial. Note, I am not posting *everything* necessary to create a window, just the creation code. You'd still need to create a message loop.
*** Source Snippet Removed ***
I know there's some graphics specific code in there but even if you take that out, the effort required to create a window is way above what it should be.

You're not just creating a window, you're determining the available video modes, creating a windowed or fullscreen mode (including the mode switch) window, creating the GL context and grabbing input focus. The equivalent Windows code is probably worse. As you can see in Mayrel's example, to create a simple window takes a whooping 3 lines of code. (XCreateSimpleWIndow, XMapWindow, XSync)

Share this post


Link to post
Share on other sites
Sign in to follow this