view src/App.cpp @ 7:713e3c5db1e1

just comments
author Eris Caffee <discordia@eldalin.com>
date Wed, 18 Apr 2012 00:53:10 -0500
parents 1b73e60d53b4
children c5c33bf5f1fb
line source
1 #include "App.h"
3 #include <cstdlib>
4 #include <iostream>
5 #include <typeinfo>
6 #include <X11/Xutil.h>
9 ////////////////////////////////////////////////////////////////////////////////
10 App::App(const std::string & appname)
11 {
12 XSetErrorHandler(&App::x_error_handler);
14 if ((dpy = XOpenDisplay(NULL)) == NULL)
15 {
16 std::cerr << "Unable to connect to display " << XDisplayName(NULL) << std::endl;
17 exit(1);
18 }
19 std::cout << "Display name : " << XDisplayName(NULL) << std::endl
20 << "Number of screens: " << ScreenCount(dpy) << std::endl
21 << "Default screen : " << DefaultScreen(dpy) << std::endl
22 << "Protocol Version : " << ProtocolVersion(dpy) << std::endl
23 << "Protocol Revision: " << ProtocolRevision(dpy) << std::endl
24 << "Server Vendor : " << ServerVendor(dpy) << std::endl
25 << "Vendor Release : " << VendorRelease(dpy) << std::endl
26 << std::endl
27 << "Display width : " << this->display_width() << std::endl
28 << "Display height : " << this->display_height() << std::endl
29 ;
31 App::BitMap * icon = new App::BitMap("xlib_App.xbm");
33 // Create the main window
34 create_window("main",
35 0, 0 ,
36 this->display_width()/2, this->display_height()/2,
37 icon);
39 // Get a reference to our WindowData structure. We need the Window handle from it for a few things.
40 App::WindowData * wd = windows["main"];
45 // We need to set the window manager hints, size hints, window name, and icon name
47 // Even though we are not passing any actual size_hints, the Xlib programming manual says to pass the flags below anyway.
48 XSizeHints *size_hints;
49 if (!(size_hints = XAllocSizeHints()))
50 {
51 std::cerr << "XAllocSizeHints: memory allocation failure" << std::endl;
52 exit(1);
53 }
54 size_hints->flags = PPosition | PSize;
56 // Get X Properties for the window and icon names.
57 XTextProperty windowName, iconName;
58 const char * ptr = appname.c_str();
59 if (XStringListToTextProperty(const_cast<char **>(&ptr), 1, &windowName) == 0)
60 {
61 std::cerr << "XStringListToTextProperty: structure allocation for windowName failed." << std::endl;;
62 exit(1);
63 }
64 ptr = icon->name.c_str();
65 if (XStringListToTextProperty(const_cast<char **>(&ptr), 1, &iconName) == 0)
66 {
67 std::cerr << "XStringListToTextProperty: structure allocation for iconName failed." << std::endl;;
68 exit(1);
69 }
71 XWMHints *wm_hints;
72 if (!(wm_hints = XAllocWMHints()))
73 {
74 std::cerr << "XAllocWMHints: memory allocation failure" << std::endl;
75 exit(0);
76 }
77 wm_hints->initial_state = NormalState;
78 wm_hints->input = True;
79 wm_hints->icon_pixmap = icon->pixmap;
80 wm_hints->flags = StateHint | IconPixmapHint | InputHint;
82 XSetWMProperties(dpy, wd->win, &windowName, &iconName,
83 NULL, 0, size_hints, wm_hints,
84 NULL);
88 // Select the event types we want to receive.
89 //Other interesting events include KeyReleaseMask and ButtonReleaseMask
90 event_mask = ExposureMask | KeyPressMask | ButtonPressMask | StructureNotifyMask ;
91 XSelectInput(dpy, wd->win, event_mask);
95 // Make sure we get delete events from the window manager.
96 // "wm_delete_window" is the Atom which corresponds to the delete
97 // window message sent by the window manager.
99 wm_delete_window = XInternAtom (dpy, "WM_DELETE_WINDOW", False);
100 XSetWMProtocols(dpy, wd->win, &wm_delete_window, 1);
103 // This give BadMatch and I don't know why.
104 // XSetWindowAttributes setwinattr;
105 // setwinattr.background_pixmap = bg_pixmap->pixmap;
106 // XChangeWindowAttributes(dpy, wd->win, CWBackPixmap, &setwinattr);
108 // Also BadMatch
109 // XSetWindowBackgroundPixmap(dpy, wd->win, icon->pixmap);
112 // XSetWindowBackgroundPixmap(dpy, wd->win, None);
115 // Map the window. Remember: this does not display the window immediately.
116 // The request is queued until events are read, or we call XFlush or XSync.
117 XMapWindow(dpy, wd->win);
118 }
120 ////////////////////////////////////////////////////////////////////////////////
121 App::~App()
122 {
123 // Ugh. I really wish I could figure out why I can't make a map of string
124 // to WindowData instead of having ton use WindowData *
125 // I'd like to eliminate this next loop.
126 for( WindowMap::iterator i = windows.begin(); i != windows.end(); ++i)
127 {
128 App::WindowData * wp = (*i).second;
129 windows.erase(i);
130 delete wp;
131 }
133 if (dpy)
134 {
135 XCloseDisplay(dpy);
136 }
137 }
139 ////////////////////////////////////////////////////////////////////////////////
140 int App::x_error_handler(Display * dpy, XErrorEvent *err)
141 {
142 char err_msg[1024];
143 err_msg[0] = 0;
144 XGetErrorText(dpy, err->error_code, err_msg, 1024);
145 std::cerr << "X11 Error"<< std::endl
146 << " display : " << DisplayString(dpy) << std::endl
147 << " serial : " << err->serial << std::endl
148 << " error_code : " << (int) err->error_code << std::endl
149 << " request_code: " << (int) err->request_code << std::endl
150 << " minor_code : " << (int) err->minor_code << std::endl
151 << err_msg << std::endl;
152 return 0;
153 }
155 ////////////////////////////////////////////////////////////////////////////////
156 void App::create_window(const std::string & win_name,
157 int x, int y,
158 unsigned int width, unsigned int height,
159 App::BitMap * icon)
160 {
161 Window win;
162 int border_width = 4; /* Border four pixels wide */
164 int screen_num = DefaultScreen(dpy);
166 /* Create opaque window */
167 win = XCreateSimpleWindow(dpy,
168 RootWindow(dpy, screen_num),
169 x, y,
170 width, height,
171 border_width,
172 None, None);
173 // BlackPixel(dpy, screen_num),
174 // WhitePixel(dpy, screen_num));
176 icon->make_pixmap(dpy, win);
178 // Add it to the window list
179 App::WindowData * win_data = new App::WindowData(win_name, win, icon);
180 windows.insert(win_pair(win_name, win_data));
181 }
183 ////////////////////////////////////////////////////////////////////////////////
184 void App::run(void)
185 {
186 XEvent e;
187 KeySym k;
188 char key_buffer[8];
189 key_buffer[7] = 0;
190 XComposeStatus compose_status;
192 int done = 0;
194 while (!done)
195 {
196 while (XCheckIfEvent(dpy, &e,
197 // *sniff* My very first lambda function in C++
198 [&](Display * d, XEvent * e, XPointer a)->Bool { return True; },
199 NULL))
200 {
201 switch (e.type)
202 {
203 case Expose:
204 // We'll only redraw the entire window at a time, so unless this is
205 // the last contiguous expose, don't draw the window.
206 if (e.xexpose.count != 0)
207 break;
208 // Draw the window contents here
209 break;
210 case ClientMessage:
211 if ((Atom)e.xclient.data.l[0] == wm_delete_window)
212 done = 1;
213 break;
214 case ButtonPress:
215 case KeyPress:
216 // Doing the lookup like this, using XLookupString, means I get the modified
217 // character back. Thus type shift+a gives me XK_A instead of XK_a
218 // If I used XKeySym I'd instead get a sequence such as this:
219 // XK_Shift_L followed by XK_a
220 //
221 // In the end, that might be a more useful way to go, but for now I'll keep
222 // things simple.
223 XLookupString(&(e.xkey), key_buffer, 7, &k, &compose_status);
224 switch (k)
225 {
226 case XK_Escape:
227 case XK_q:
228 std::cout << "Goodbye!" << std::endl;
229 done = 1;
230 break;
231 default:
232 std::cout << "You typed " << key_buffer << std::endl;
233 break;
234 }
235 default:
236 break;
237 }
238 }
240 // Do idle time things here
242 }
243 }
245 ////////////////////////////////////////////////////////////////////////////////
246 // App::BitMap
247 ////////////////////////////////////////////////////////////////////////////////
248 App::BitMap::BitMap(const std::string & file)
249 {
250 read_from_file(file);
251 }
253 ////////////////////////////////////////////////////////////////////////////////
254 App::BitMap::~BitMap()
255 {
256 if (data) { XFree(data); data = NULL; }
257 }
259 ////////////////////////////////////////////////////////////////////////////////
260 void App::BitMap::make_pixmap(Display * dpy, Drawable d)
261 {
262 pixmap = XCreateBitmapFromData(dpy, d, (char *) data, width, height);
263 }
265 ////////////////////////////////////////////////////////////////////////////////
266 int App::BitMap::read_from_file(const std::string & file)
267 {
268 if (BitmapSuccess != XReadBitmapFileData(file.c_str(), &width, &height, &data, NULL, NULL))
269 {
270 return 0;
271 }
273 name = file;
274 size_t p = name.rfind("/");
275 if (p != std::string::npos)
276 {
277 name.replace(0, p+1, "");
278 }
279 return 1;
280 }