xglcomp

view src/main.cc @ 3:e831d38e6faa

textures
author John Tsiombikas <nuclear@member.fsf.org>
date Fri, 22 Jan 2016 07:46:47 +0200
parents 876efea9424c
children 86e57e56a454
line source
1 #include <stdio.h>
2 #include <stdlib.h>
3 #include <unistd.h>
4 #include <X11/Xlib.h>
5 #include <X11/Xutil.h>
6 #include <X11/Xatom.h>
7 #include <X11/extensions/Xcomposite.h>
8 #include <X11/extensions/Xdamage.h>
9 #include "cwin.h"
10 #include "opengl.h"
11 #include "logger.h"
13 static bool register_compositor();
14 static void start_comp();
15 static void manage_window(Window xwin);
16 static void unmanage_window(Window xwin);
17 static void redraw();
18 static void draw_window(CompWindow *cwin);
19 static void reshape(int x, int y);
21 Display *dpy;
22 int screen_num;
23 Window root_win, comp_win;
24 int root_width, root_height;
26 int main(int argc, char **argv)
27 {
28 if(!(dpy = XOpenDisplay(0))) {
29 log_error("failed to open X display\n");
30 return 1;
31 }
32 screen_num = DefaultScreen(dpy);
33 root_win = RootWindow(dpy, screen_num);
34 root_width = DisplayWidth(dpy, screen_num);
35 root_height = DisplayHeight(dpy, screen_num);
36 log_info("display size %dx%d\n", root_width, root_height);
38 int xcomp_ev_base, xcomp_err_base;
39 if(!XCompositeQueryExtension(dpy, &xcomp_ev_base, &xcomp_err_base)) {
40 log_error("X server doesn't support the composite extension\n");
41 return 1;
42 }
43 int xcomp_ver_major = 0, xcomp_ver_minor = 4;
44 XCompositeQueryVersion(dpy, &xcomp_ver_major, &xcomp_ver_minor);
45 log_info("Found composite extension version %d.%d\n", xcomp_ver_major, xcomp_ver_minor);
46 if(xcomp_ver_major <= 0 && xcomp_ver_minor < 3) {
47 // for NameWindowPixmap & CompositeGetoverlayWindow
48 log_error("I need at least version 0.3\n");
49 return 1;
50 }
52 int xdmg_ev_base, xdmg_err_base;
53 if(!XDamageQueryExtension(dpy, &xdmg_ev_base, &xdmg_err_base)) {
54 log_error("X server doesn't support the damage extension\n");
55 return 1;
56 }
57 // TODO also XFixes ?
59 if(!register_compositor()) {
60 return 1;
61 }
63 comp_win = XCompositeGetOverlayWindow(dpy, root_win);
64 if(!create_gl(comp_win)) {
65 return 1;
66 }
68 start_comp();
69 reshape(root_width, root_height);
70 redraw();
72 for(;;) {
73 XEvent ev;
74 XNextEvent(dpy, &ev);
76 CompWindow *cwin;
77 switch(ev.type) {
78 case CreateNotify:
79 manage_window(ev.xcreatewindow.window);
80 break;
82 case ConfigureNotify:
83 break;
85 case DestroyNotify:
86 unmanage_window(ev.xdestroywindow.window);
87 break;
89 case MapNotify:
90 if((cwin = find_window_xid(ev.xmap.window))) {
91 cwin->mapped = true;
92 }
93 break;
95 case UnmapNotify:
96 if((cwin = find_window_xid(ev.xunmap.window))) {
97 cwin->mapped = false;
98 }
99 break;
101 case ReparentNotify:
102 if(ev.xreparent.parent == root_win) {
103 manage_window(ev.xreparent.window);
104 } else {
105 unmanage_window(ev.xreparent.window);
106 }
107 break;
109 case CirculateNotify:
110 break;
112 case Expose:
113 // TODO?
114 break;
116 default:
117 if(ev.type == xdmg_ev_base + XDamageNotify) {
118 }
119 }
120 }
121 }
123 static bool register_compositor()
124 {
125 char atom_name[64];
126 sprintf(atom_name, "_NET_WM_CM_S%d", screen_num);
127 Atom xa_wm_cm = XInternAtom(dpy, atom_name, False);
129 Window win = XGetSelectionOwner(dpy, xa_wm_cm);
130 if(win != None) {
131 log_error("Another compositor is running. Stop it and try again.\n");
132 return false;
133 }
135 win = XCreateSimpleWindow(dpy, root_win, 0, 0, 1, 1, 0, None, None);
136 XSetSelectionOwner(dpy, xa_wm_cm, win, 0);
137 return true;
138 }
140 static void start_comp()
141 {
142 XGrabServer(dpy);
143 XCompositeRedirectSubwindows(dpy, root_win, CompositeRedirectManual);
144 XSelectInput(dpy, root_win, SubstructureNotifyMask | ExposureMask | StructureNotifyMask);
146 // manage all top-level windows
147 Window root_ret, parent;
148 Window *children;
149 unsigned int num_children;
150 XQueryTree(dpy, root_win, &root_ret, &parent, &children, &num_children);
152 for(unsigned int i=0; i<num_children; i++) {
153 manage_window(children[i]);
154 }
155 log_info("starting compositor, managing %u top-level windows\n", num_children);
156 XFree(children);
158 XUngrabServer(dpy);
159 }
161 static void manage_window(Window xwin)
162 {
163 //log_debug("manage_window %u\n", xwin);
164 CompWindow *cwin = new CompWindow(xwin);
165 XGetWindowAttributes(dpy, xwin, &cwin->attr);
166 cwin->mapped = cwin->attr.map_state != IsUnmapped;
167 add_window(cwin);
168 }
170 static void unmanage_window(Window xwin)
171 {
172 //log_debug("unmanage_window %u\n", xwin);
173 CompWindow *cwin = find_window_xid(xwin);
174 if(!cwin) return;
176 if(cwin->xpixmap) {
177 XFreePixmap(dpy, cwin->xpixmap);
178 }
180 remove_window(cwin);
181 delete cwin;
182 }
184 static void redraw()
185 {
186 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
188 glPushAttrib(GL_ENABLE_BIT);
189 glEnable(GL_TEXTURE_2D);
190 glEnable(GL_BLEND);
191 glBlendFunc(GL_ONE, GL_ONE);
193 int num_win = get_window_count();
194 for(int i=0; i<num_win; i++) {
195 CompWindow *cwin = get_window(i);
197 if(!cwin->mapped) continue;
199 if(cwin->attr.x + cwin->attr.width <= 0 ||
200 cwin->attr.y + cwin->attr.height <= 0 ||
201 cwin->attr.x >= root_width || cwin->attr.y >= root_height) {
202 continue;
203 }
205 draw_window(cwin);
206 }
208 glPopAttrib();
210 glXSwapBuffers(dpy, comp_win);
211 }
213 static void draw_window(CompWindow *cwin)
214 {
215 if(!cwin->xpixmap) {
216 cwin->xpixmap = XCompositeNameWindowPixmap(dpy, cwin->xwin);
217 if(!cwin->xpixmap) {
218 log_warning("failed to get pixmap\n");
219 return;
220 }
221 cwin->tex.set_image(dpy, cwin->xpixmap);
222 }
224 glBindTexture(GL_TEXTURE_2D, cwin->tex.get_id());
226 glBegin(GL_QUADS);
227 glColor3f(0.3, 0.3, 0.3);
228 glTexCoord2f(0, 0);
229 glVertex2f(cwin->attr.x, cwin->attr.y);
230 glTexCoord2f(1, 0);
231 glVertex2f(cwin->attr.x + cwin->attr.width, cwin->attr.y);
232 glTexCoord2f(1, 1);
233 glVertex2f(cwin->attr.x + cwin->attr.width, cwin->attr.y + cwin->attr.height);
234 glTexCoord2f(0, 1);
235 glVertex2f(cwin->attr.x, cwin->attr.y + cwin->attr.height);
236 glEnd();
237 }
239 static void reshape(int x, int y)
240 {
241 glViewport(0, 0, x, y);
243 glMatrixMode(GL_PROJECTION);
244 glLoadIdentity();
245 glOrtho(0, x, y, 0, -1, 1);
246 }