view src/App.cpp @ 5:008e28de2870

Saving work
author Eris Caffee <discordia@eldalin.com>
date Mon, 16 Apr 2012 10:32:59 -0500
parents c6dce2064bfb
children 1b73e60d53b4
line source
1 #include "App.h"
3 #include <cstdlib>
4 #include <iostream>
5 #include <typeinfo>
6 #include <X11/Xutil.h>
8 ////////////////////////////////////////////////////////////////////////////////
9 App::App(const std::string & appname)
10 {
11 XSetErrorHandler(&App::x_error_handler);
13 if ((dpy = XOpenDisplay(NULL)) == NULL)
14 {
15 std::cerr << "Unable to connect to display " << XDisplayName(NULL) << std::endl;
16 exit(1);
17 }
18 std::cout << "Display name : " << XDisplayName(NULL) << std::endl
19 << "Number of screens: " << ScreenCount(dpy) << std::endl
20 << "Default screen : " << DefaultScreen(dpy) << std::endl
21 << "Protocol Version : " << ProtocolVersion(dpy) << std::endl
22 << "Protocol Revision: " << ProtocolRevision(dpy) << std::endl
23 << "Server Vendor : " << ServerVendor(dpy) << std::endl
24 << "Vendor Release : " << VendorRelease(dpy) << std::endl
25 << std::endl
26 << "Display width : " << this->display_width() << std::endl
27 << "Display height : " << this->display_height() << std::endl
28 ;
30 App::BitMap * icon = new App::BitMap("xlib_App.xbm");
32 // Create the main window
33 create_window("main",
34 0, 0 ,
35 this->display_width()/2, this->display_height()/2,
36 icon);
38 // Get a reference to our WindowData structure. We need the Window handle from it for a few things.
39 App::WindowData * wd = windows["main"];
44 // We need to set the window manager hints, size hints, window name, and icon name
46 // Even though we are not passing any actual size_hints, the Xlib programming manual says to pass the flags below anyway.
47 XSizeHints *size_hints;
48 if (!(size_hints = XAllocSizeHints()))
49 {
50 std::cerr << "XAllocSizeHints: memory allocation failure" << std::endl;
51 exit(1);
52 }
53 size_hints->flags = PPosition | PSize;
55 // Get X Properties for the window and icon names.
56 XTextProperty windowName, iconName;
57 const char * ptr = appname.c_str();
58 if (XStringListToTextProperty(const_cast<char **>(&ptr), 1, &windowName) == 0)
59 {
60 std::cerr << "XStringListToTextProperty: structure allocation for windowName failed." << std::endl;;
61 exit(1);
62 }
63 ptr = icon->name.c_str();
64 if (XStringListToTextProperty(const_cast<char **>(&ptr), 1, &iconName) == 0)
65 {
66 std::cerr << "XStringListToTextProperty: structure allocation for iconName failed." << std::endl;;
67 exit(1);
68 }
70 XWMHints *wm_hints;
71 if (!(wm_hints = XAllocWMHints()))
72 {
73 std::cerr << "XAllocWMHints: memory allocation failure" << std::endl;
74 exit(0);
75 }
76 wm_hints->initial_state = NormalState;
77 wm_hints->input = True;
78 wm_hints->icon_pixmap = icon->pixmap;
79 wm_hints->flags = StateHint | IconPixmapHint | InputHint;
81 XSetWMProperties(dpy, wd->win, &windowName, &iconName,
82 NULL, 0, size_hints, wm_hints,
83 NULL);
87 // Select the event types we want to receive.
88 //Other interesting events include KeyReleaseMask and ButtonReleaseMask
89 XSelectInput(dpy, wd->win, ExposureMask | KeyPressMask | ButtonPressMask | StructureNotifyMask);
93 // Make sure we get delete events from the window manager.
94 // "wm_delete_window" is the Atom which corresponds to the delete
95 // window message sent by the window manager.
97 wm_delete_window = XInternAtom (dpy, "WM_DELETE_WINDOW", False);
98 XSetWMProtocols(dpy, wd->win, &wm_delete_window, 1);
101 // This give BadMatch and I don't know why.
102 // XSetWindowAttributes setwinattr;
103 // setwinattr.background_pixmap = bg_pixmap->pixmap;
104 // XChangeWindowAttributes(dpy, wd->win, CWBackPixmap, &setwinattr);
106 // Also BadMatch
107 // XSetWindowBackgroundPixmap(dpy, wd->win, icon->pixmap);
110 // XSetWindowBackgroundPixmap(dpy, wd->win, None);
113 // Map the window. Remember: this does not display the window immediately.
114 // The request is queued until events are read, or we call XFlush or XSync.
115 XMapWindow(dpy, wd->win);
116 }
118 ////////////////////////////////////////////////////////////////////////////////
119 App::~App()
120 {
121 // Ugh. I really wish I could figure out why I can't make a map of string
122 // to WindowData instead of having ton use WindowData *
123 // I'd like to eliminate this next loop.
124 for( WindowMap::iterator i = windows.begin(); i != windows.end(); ++i)
125 {
126 App::WindowData * wp = (*i).second;
127 windows.erase(i);
128 delete wp;
129 }
131 if (dpy)
132 {
133 XCloseDisplay(dpy);
134 }
135 }
137 ////////////////////////////////////////////////////////////////////////////////
138 int App::x_error_handler(Display * dpy, XErrorEvent *err)
139 {
140 char err_msg[1024];
141 err_msg[0] = 0;
142 XGetErrorText(dpy, err->error_code, err_msg, 1024);
143 std::cerr << "X11 Error"<< std::endl
144 << " display : " << DisplayString(dpy) << std::endl
145 << " serial : " << err->serial << std::endl
146 << " error_code : " << (int) err->error_code << std::endl
147 << " request_code: " << (int) err->request_code << std::endl
148 << " minor_code : " << (int) err->minor_code << std::endl
149 << err_msg << std::endl;
150 return 0;
151 }
153 ////////////////////////////////////////////////////////////////////////////////
154 void App::create_window(const std::string & win_name,
155 int x, int y,
156 unsigned int width, unsigned int height,
157 App::BitMap * icon)
158 {
159 Window win;
160 int border_width = 4; /* Border four pixels wide */
162 int screen_num = DefaultScreen(dpy);
164 /* Create opaque window */
165 win = XCreateSimpleWindow(dpy,
166 RootWindow(dpy, screen_num),
167 x, y,
168 width, height,
169 border_width,
170 None, None);
171 // BlackPixel(dpy, screen_num),
172 // WhitePixel(dpy, screen_num));
174 icon->make_pixmap(dpy, win);
176 // Add it to the window list
177 App::WindowData * win_data = new App::WindowData(win_name, win, icon);
178 windows.insert(win_pair(win_name, win_data));
179 }
181 ////////////////////////////////////////////////////////////////////////////////
182 void App::run(void)
183 {
184 XEvent e;
185 int done = 0;
186 while (!done)
187 {
188 XNextEvent(dpy, &e);
189 switch (e.type)
190 {
191 case Expose:
192 // We'll only redraw the entire window at a time, so unless this is
193 // the last contiguous expose, don't draw the window.
194 if (e.xexpose.count != 0)
195 break;
196 // Draw the window contents here
197 break;
198 case ClientMessage:
199 if ((Atom)e.xclient.data.l[0] == wm_delete_window)
200 done = 1;
201 break;
202 case ButtonPress:
203 case KeyPress:
204 done = 1;
205 default:
206 break;
207 }
208 }
209 }
211 ////////////////////////////////////////////////////////////////////////////////
212 // App::BitMap
213 ////////////////////////////////////////////////////////////////////////////////
214 App::BitMap::BitMap(const std::string & file)
215 {
216 read_from_file(file);
217 }
219 ////////////////////////////////////////////////////////////////////////////////
220 App::BitMap::~BitMap()
221 {
222 if (data) { XFree(data); data = NULL; }
223 }
225 ////////////////////////////////////////////////////////////////////////////////
226 void App::BitMap::make_pixmap(Display * dpy, Drawable d)
227 {
228 pixmap = XCreateBitmapFromData(dpy, d, (char *) data, width, height);
229 }
231 ////////////////////////////////////////////////////////////////////////////////
232 int App::BitMap::read_from_file(const std::string & file)
233 {
234 if (BitmapSuccess != XReadBitmapFileData(file.c_str(), &width, &height, &data, NULL, NULL))
235 {
236 return 0;
237 }
239 name = file;
240 size_t p = name.rfind("/");
241 if (p != std::string::npos)
242 {
243 name.replace(0, p+1, "");
244 }
245 return 1;
246 }