1 // -*- mode: C++; indent-tabs-mode: nil; c-basic-offset: 2; -*-
2 // Display.cc for Blackbox - an X11 Window manager
3 // Copyright (c) 2001 - 2005 Sean 'Shaleh' Perry <shaleh@debian.org>
4 // Copyright (c) 1997 - 2000, 2002 - 2005
5 // Bradley T Hughes <bhughes at trolltech.com>
6 //
7 // Permission is hereby granted, free of charge, to any person obtaining a
8 // copy of this software and associated documentation files (the "Software"),
9 // to deal in the Software without restriction, including without limitation
10 // the rights to use, copy, modify, merge, publish, distribute, sublicense,
11 // and/or sell copies of the Software, and to permit persons to whom the
12 // Software is furnished to do so, subject to the following conditions:
13 //
14 // The above copyright notice and this permission notice shall be included in
15 // all copies or substantial portions of the Software.
16 //
17 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18 // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19 // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
20 // THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21 // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
22 // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
23 // DEALINGS IN THE SOFTWARE.
24
25 #include "Display.hh"
26
27 #include <algorithm>
28 #include <cstdlib>
29
30 #include <X11/Xutil.h>
31
32 #include <assert.h>
33 #include <fcntl.h>
34 #include <stdio.h>
35
36 namespace bt {
37
38 void createBitmapLoader(const Display &display);
39 void destroyBitmapLoader(void);
40
41 void createColorCache(const Display &display);
42 void destroyColorCache(void);
43
44
45 void createFontCache(const Display &display);
46 void destroyFontCache(void);
47
48
49 void createPenCache(const Display &display);
50 void destroyPenCache(void);
51
52
53 void createPixmapCache(const Display &display);
54 void destroyPixmapCache(void);
55
56
57 void destroyColorTables(void);
58
59
60 #ifdef MITSHM
61 void startupShm(const Display &display);
62 #endif // MITSHM
63
64 } // namespace bt
65
66
Display(const char * dpy_name,bool multi_head)67 bt::Display::Display(const char *dpy_name, bool multi_head) {
68 if (!(xdisplay = XOpenDisplay(dpy_name))) {
69 fprintf(stderr, "bt::Display: failed to open display '%s'\n",
70 dpy_name ? dpy_name : "");
71 std::exit(2);
72 }
73
74 #ifdef DEBUG
75 XSynchronize(xdisplay, True);
76 #endif // DEBUG
77
78 if (fcntl(XConnectionNumber(xdisplay), F_SETFD, 1) == -1) {
79 fprintf(stderr, "bt::Display: failed to mark connection close-on-exec\n");
80 std::exit(2);
81 }
82
83 if (!multi_head || ScreenCount(xdisplay) == 1) {
84 screen_info_count = 1;
85 screen_info_list = new bt::ScreenInfo*[screen_info_count];
86 screen_info_list[0] = new bt::ScreenInfo(*this, DefaultScreen(xdisplay));
87 } else {
88 screen_info_count = ScreenCount(xdisplay);
89 screen_info_list = new bt::ScreenInfo*[screen_info_count];
90 for (unsigned int i = 0; i < screen_info_count; ++i)
91 screen_info_list[i] = new bt::ScreenInfo(*this, i);
92 }
93 createBitmapLoader(*this);
94 createColorCache(*this);
95 createFontCache(*this);
96 createPenCache(*this);
97 createPixmapCache(*this);
98
99 #ifdef MITSHM
100 startupShm(*this);
101 #endif // MITSHM
102 }
103
104
~Display()105 bt::Display::~Display() {
106 destroyColorTables();
107 destroyPixmapCache();
108 destroyPenCache();
109 destroyFontCache();
110 destroyColorCache();
111 destroyBitmapLoader();
112
113 std::for_each(screen_info_list, screen_info_list + screen_info_count,
114 bt::PointerAssassin());
115 delete [] screen_info_list;
116
117 XCloseDisplay(xdisplay);
118 }
119
120
screenInfo(unsigned int i) const121 const bt::ScreenInfo &bt::Display::screenInfo(unsigned int i) const {
122 if (screen_info_count == 1)
123 return *(screen_info_list[0]);
124
125 assert(i < screen_info_count);
126 return *screen_info_list[i];
127 }
128
129
ScreenInfo(bt::Display & d,unsigned int num)130 bt::ScreenInfo::ScreenInfo(bt::Display& d, unsigned int num)
131 : _display(d), _screennumber(num)
132 {
133 _rootwindow = RootWindow(_display.XDisplay(), _screennumber);
134
135 _rect.setSize(WidthOfScreen(ScreenOfDisplay(_display.XDisplay(),
136 _screennumber)),
137 HeightOfScreen(ScreenOfDisplay(_display.XDisplay(),
138 _screennumber)));
139
140 /*
141 If the default depth is at least 8 we will use that,
142 otherwise we try to find the largest TrueColor visual.
143 Preference is given to 24 bit over larger depths if 24 bit is an option.
144 */
145
146 _depth = DefaultDepth(_display.XDisplay(), _screennumber);
147 _visual = DefaultVisual(_display.XDisplay(), _screennumber);
148 _colormap = DefaultColormap(_display.XDisplay(), _screennumber);
149
150 if (_depth < 8) {
151 // search for a TrueColor Visual... if we can't find one...
152 // we will use the default visual for the screen
153 XVisualInfo vinfo_template, *vinfo_return;
154 int vinfo_nitems;
155 int best = -1;
156
157 vinfo_template.screen = _screennumber;
158 vinfo_template.c_class = TrueColor;
159
160 vinfo_return = XGetVisualInfo(_display.XDisplay(),
161 VisualScreenMask | VisualClassMask,
162 &vinfo_template, &vinfo_nitems);
163 if (vinfo_return) {
164 int max_depth = 1;
165 for (int i = 0; i < vinfo_nitems; ++i) {
166 if (vinfo_return[i].depth < max_depth ||
167 // prefer 24 bit over 32
168 (max_depth == 24 && vinfo_return[i].depth > 24))
169 continue;
170 max_depth = vinfo_return[i].depth;
171 best = i;
172 }
173 if (max_depth < _depth) best = -1;
174 }
175
176 if (best != -1) {
177 _depth = vinfo_return[best].depth;
178 _visual = vinfo_return[best].visual;
179 _colormap = XCreateColormap(_display.XDisplay(), _rootwindow,
180 _visual, AllocNone);
181 }
182
183 XFree(vinfo_return);
184 }
185
186 // get the default display string and strip the screen number
187 std::string default_string = DisplayString(_display.XDisplay());
188 const std::string::size_type pos = default_string.rfind(".");
189 if (pos != std::string::npos)
190 default_string.resize(pos);
191
192 _displaystring = std::string("DISPLAY=") + default_string + '.' +
193 bt::itostring(_screennumber);
194 }
195