# HG changeset patch # User John Tsiombikas # Date 1453437063 -7200 # Node ID 876efea9424c209e85d2f1c74c72d93eac063d0b # Parent b2b7cb950c289a6ee88059538d43177100c5f001 OpenGL diff -r b2b7cb950c28 -r 876efea9424c src/cwin.cc --- a/src/cwin.cc Thu Jan 21 22:50:10 2016 +0200 +++ b/src/cwin.cc Fri Jan 22 06:31:03 2016 +0200 @@ -5,6 +5,12 @@ static std::vector cwinlist; +CompWindow::CompWindow(Window xid) +{ + xwin = xid; + xpixmap = 0; +} + void add_window(CompWindow *cwin) { if(have_window(cwin)) { @@ -15,7 +21,7 @@ cwinlist.push_back(cwin); } -bool delete_window(CompWindow *cwin) +bool remove_window(CompWindow *cwin) { auto it = std::find(cwinlist.begin(), cwinlist.end(), cwin); if(it != cwinlist.end()) { diff -r b2b7cb950c28 -r 876efea9424c src/cwin.h --- a/src/cwin.h Thu Jan 21 22:50:10 2016 +0200 +++ b/src/cwin.h Fri Jan 22 06:31:03 2016 +0200 @@ -3,15 +3,18 @@ #include -struct CompWindow { +class CompWindow { +public: Window xwin; Pixmap xpixmap; - struct CompWindow *next, *prev; + XWindowAttributes attr; + + CompWindow(Window xid = 0); }; void add_window(CompWindow *cwin); -bool delete_window(CompWindow *cwin); +bool remove_window(CompWindow *cwin); bool have_window(CompWindow *cwin); CompWindow *find_window_xid(Window xid); CompWindow *find_window_pixmap(Pixmap pix); diff -r b2b7cb950c28 -r 876efea9424c src/logger.c --- a/src/logger.c Thu Jan 21 22:50:10 2016 +0200 +++ b/src/logger.c Fri Jan 22 06:31:03 2016 +0200 @@ -3,6 +3,11 @@ #include #include #include +#ifdef _MSC_VER +#include +#else +#include +#endif #include "logger.h" #if defined(unix) || defined(__unix__) || defined(__APPLE__) @@ -214,7 +219,16 @@ #if defined(unix) || defined(__unix__) || defined(__APPLE__) if(isatty(fileno(targ->fp)) && type != LOG_INFO) { int c = typecolor(type); - fprintf(targ->fp, "\033[%dm%s\033[0m", c, str); + + int len = strlen(str); + if(str[len - 1] == '\n') { + char *s = alloca(len); + memcpy(s, str, len); + s[len - 1] = 0; + fprintf(targ->fp, "\033[%dm%s\033[0m\n", c, s); + } else { + fprintf(targ->fp, "\033[%dm%s\033[0m", c, str); + } } else #endif { diff -r b2b7cb950c28 -r 876efea9424c src/main.cc --- a/src/main.cc Thu Jan 21 22:50:10 2016 +0200 +++ b/src/main.cc Fri Jan 22 06:31:03 2016 +0200 @@ -6,16 +6,21 @@ #include #include #include -#include #include "cwin.h" +#include "opengl.h" #include "logger.h" static bool register_compositor(); +static void start_comp(); +static void manage_window(Window xwin); +static void unmanage_window(Window xwin); +static void redraw(); +static void reshape(int x, int y); -static Display *dpy; -static int scr; -static Window root_win; -static int root_width, root_height; +Display *dpy; +int screen_num; +Window root_win, comp_win; +int root_width, root_height; int main(int argc, char **argv) { @@ -23,21 +28,23 @@ log_error("failed to open X display\n"); return 1; } - scr = DefaultScreen(dpy); - root_win = RootWindow(dpy, scr); - root_width = DisplayWidth(dpy, scr); - root_height = DisplayHeight(dpy, scr); + screen_num = DefaultScreen(dpy); + root_win = RootWindow(dpy, screen_num); + root_width = DisplayWidth(dpy, screen_num); + root_height = DisplayHeight(dpy, screen_num); log_info("display size %dx%d\n", root_width, root_height); - int xcomp_ev_base, xcomp_err_base, xcomp_ver_major, xcomp_ver_minor; + int xcomp_ev_base, xcomp_err_base; if(!XCompositeQueryExtension(dpy, &xcomp_ev_base, &xcomp_err_base)) { log_error("X server doesn't support the composite extension\n"); return 1; } + int xcomp_ver_major = 0, xcomp_ver_minor = 4; XCompositeQueryVersion(dpy, &xcomp_ver_major, &xcomp_ver_minor); log_info("Found composite extension version %d.%d\n", xcomp_ver_major, xcomp_ver_minor); - if(xcomp_ver_major <= 10 && xcomp_ver_minor < 2) { - log_error("I need at least version 1.2\n"); // for NameWindowPixmap + if(xcomp_ver_major <= 0 && xcomp_ver_minor < 3) { + // for NameWindowPixmap & CompositeGetoverlayWindow + log_error("I need at least version 0.3\n"); return 1; } @@ -52,21 +59,65 @@ return 1; } - XGrabServer(dpy); - XCompositeRedirectSubwindows(dpy, root_win, CompositeRedirectAutomatic); - XUngrabServer(dpy); + comp_win = XCompositeGetOverlayWindow(dpy, root_win); + if(!create_gl(comp_win)) { + return 1; + } + + start_comp(); + reshape(root_width, root_height); + redraw(); for(;;) { XEvent ev; XNextEvent(dpy, &ev); - // TODO + + switch(ev.type) { + case CreateNotify: + manage_window(ev.xcreatewindow.window); + break; + + case ConfigureNotify: + break; + + case DestroyNotify: + unmanage_window(ev.xdestroywindow.window); + break; + + case MapNotify: + break; + case UnmapNotify: + break; + + case ReparentNotify: + if(ev.xreparent.parent == root_win) { + manage_window(ev.xreparent.window); + } else { + unmanage_window(ev.xreparent.window); + } + break; + + case CirculateNotify: + break; + + case Expose: + if(ev.xexpose.window == root_win) { + log_debug("expose\n"); + // TODO + } + break; + + default: + if(ev.type == xdmg_ev_base + XDamageNotify) { + } + } } } static bool register_compositor() { char atom_name[64]; - sprintf(atom_name, "_NET_WM_CM_S%d", scr); + sprintf(atom_name, "_NET_WM_CM_S%d", screen_num); Atom xa_wm_cm = XInternAtom(dpy, atom_name, False); Window win = XGetSelectionOwner(dpy, xa_wm_cm); @@ -79,3 +130,76 @@ XSetSelectionOwner(dpy, xa_wm_cm, win, 0); return true; } + +static void start_comp() +{ + XGrabServer(dpy); + XCompositeRedirectSubwindows(dpy, root_win, CompositeRedirectManual); + XSelectInput(dpy, root_win, SubstructureNotifyMask | ExposureMask | StructureNotifyMask); + + // manage all top-level windows + Window root_ret, parent; + Window *children; + unsigned int num_children; + XQueryTree(dpy, root_win, &root_ret, &parent, &children, &num_children); + + for(unsigned int i=0; iattr); + add_window(cwin); +} + +static void unmanage_window(Window xwin) +{ + //log_debug("unmanage_window %u\n", xwin); + CompWindow *cwin = find_window_xid(xwin); + if(cwin) { + remove_window(cwin); + delete cwin; + } +} + +static void redraw() +{ + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + + glEnable(GL_BLEND); + glBlendFunc(GL_ONE, GL_ONE); + + int num_win = get_window_count(); + for(int i=0; iattr.x, cwin->attr.y); + glVertex2f(cwin->attr.x + cwin->attr.width, cwin->attr.y); + glVertex2f(cwin->attr.x + cwin->attr.width, cwin->attr.y + cwin->attr.height); + glVertex2f(cwin->attr.x, cwin->attr.y + cwin->attr.height); + glEnd(); + } + + glDisable(GL_BLEND); + + glXSwapBuffers(dpy, comp_win); +} + +static void reshape(int x, int y) +{ + glViewport(0, 0, x, y); + + glMatrixMode(GL_PROJECTION); + glLoadIdentity(); + glOrtho(0, x, y, 0, -1, 1); +} diff -r b2b7cb950c28 -r 876efea9424c src/opengl.cc --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/opengl.cc Fri Jan 22 06:31:03 2016 +0200 @@ -0,0 +1,48 @@ +#include "opengl.h" +#include "logger.h" + +extern Display *dpy; +extern Window root_win; +extern int screen_num; +extern int root_width, root_height; + +GLXContext create_gl(Window xwin) +{ + static int glxattr[] = { + GLX_USE_GL, 1, + GLX_RGBA, + GLX_DOUBLEBUFFER, + GLX_RED_SIZE, 8, + GLX_GREEN_SIZE, 8, + GLX_BLUE_SIZE, 8, + GLX_DEPTH_SIZE, 16, + None + }; + + XVisualInfo *vis_info = glXChooseVisual(dpy, screen_num, glxattr); + if(!vis_info) { + log_error("failed to find suitable GLX visual\n"); + return 0; + } + + GLXContext ctx = glXCreateContext(dpy, vis_info, 0, True); + if(!ctx) { + log_error("failed to create OpenGL context\n"); + XFree(vis_info); + return 0; + } + XFree(vis_info); + + if(!glXMakeCurrent(dpy, xwin, ctx)) { + log_error("failed to attach OpenGL context to window\n"); + glXDestroyContext(dpy, ctx); + return 0; + } + return ctx; +} + +void destroy_gl(GLXContext ctx) +{ + glXMakeCurrent(dpy, 0, 0); + glXDestroyContext(dpy, ctx); +} diff -r b2b7cb950c28 -r 876efea9424c src/opengl.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/opengl.h Fri Jan 22 06:31:03 2016 +0200 @@ -0,0 +1,11 @@ +#ifndef OPENGL_H_ +#define OPENGL_H_ + +#include +#include +#include + +GLXContext create_gl(Window xwin); +void destroy_gl(GLXContext ctx); + +#endif // OPENGL_H_