LOGIN / SIGN UP
2 Author: Claes Nästén
Date: Wed Nov 04 15:12:07 +0100 2009
Subject: Split up Client constructor in more methods.

src/Client.cc
 
72 @@ -72,6 +72,10 @@
72 {
73 // Construct the client
74 PScreen::instance()->grabServer();
75 if (! validate() || ! getAndUpdateWindowAttributes()) {
76 PScreen::instance()->ungrabServer(true);
77 return;
78 }
79
80 // PWinObj attributes
81 _window = new_client;
...  
86 @@ -82,42 +86,6 @@
86 _title.setId(_id);
87 _title.infoAdd(PDecor::TitleItem::INFO_ID);
88
85 if (! validate()) {
86 #ifdef DEBUG
87 cerr << __FILE__ << "@" << __LINE__ << ": " << "Couldn't validate client." << endl;
88 #endif // DEBUG
89 PScreen::instance()->ungrabServer(true);
90 return;
91 }
92
93 XWindowAttributes attr;
94 if (! XGetWindowAttributes(_dpy, _window, &attr)) {
95 #ifdef DEBUG
96 cerr << __FILE__ << "@" << __LINE__ << ": " << "Client died." << endl;
97 #endif // DEBUG
98 PScreen::instance()->ungrabServer(true);
99 return;
100 }
101 _gm.x = attr.x;
102 _gm.y = attr.y;
103 _gm.width = attr.width;
104 _gm.height = attr.height;
105
106 _cmap = attr.colormap;
107 _size = XAllocSizeHints();
108
109 // get trans window and the window attributes
110 getTransientForHint();
111
112 XSetWindowAttributes sattr;
113 sattr.event_mask =
114 PropertyChangeMask|StructureNotifyMask|FocusChangeMask;
115 sattr.do_not_propagate_mask =
116 ButtonPressMask|ButtonReleaseMask|ButtonMotionMask;
117
118 // We don't want these masks to be propagated down to the frame
119 XChangeWindowAttributes(_dpy, _window, CWEventMask|CWDontPropagate, &sattr);
120
125 #ifdef HAVE_SHAPE
126 if (PScreen::instance()->hasExtensionShape()) {
127 XShapeSelectInput(_dpy, _window, ShapeNotifyMask);
...  
111 @@ -143,144 +111,20 @@
111 AutoProperty *ap = readAutoprops(WindowManager::instance()->isStartup()
112 ? APPLY_ON_NEW : APPLY_ON_START);
113
146 readMwmHints(); // read atoms
147 readEwmhHints();
148 readPekwmHints();
149 readIcon();
150 readClientPid();
151 readClientRemote();
152 getWMProtocols();
153
154 ulong initial_state = NormalState;
155 XWMHints* hints = XGetWMHints(_dpy, _window);
156 if (hints) {
157 // get the input focus mode
158 if (hints->flags&InputHint) { // FIXME: More logic needed
159 _wm_hints_input = hints->input;
160 }
129 readHints();
130 findOrCreateFrame(ap);
131 setInitialState();
132
165 // Get initial state of the window
166 if (hints->flags&StateHint) {
167 initial_state = hints->initial_state;
168 }
169
170 XFree(hints);
171 }
172
173 // Set state either specified in hint
174 if (getWmState() == IconicState) {
175 _iconified = true;
176 }
177
178 if (_iconified || initial_state == IconicState) {
179 _iconified = true;
180 _mapped = true;
181 unmapWindow();
182 } else {
183 setWmState(initial_state);
184 }
185
186 // grab keybindings and mousebutton actions
155 // Grab keybindings and mousebutton actions
156 KeyGrabber::instance()->grabKeys(_window);
157 grabButtons();
158
191 // don't want to spread the giveInputFocuses
192 bool do_focus = is_new ? Config::instance()->isFocusNew() : false;
193 bool do_autogroup = true;
194 bool is_active = getPekwmFrameActive();
195
196 // If pekwm is already running, check against autoproperty then
197 // tagged frame. If starting up, check if it has a FRAME_ID and if not
198 // use autoproperties.
199 if (WindowManager::instance()->isStartup()) {
200 // Check for tagged frame
201 Frame *frame = Frame::getTagFrame();
202 if (frame && frame->isMapped()) {
203 _parent = frame;
204 frame->addChild(this);
205
206 if (! Frame::getTagBehind()) {
207 frame->activateChild(this);
208 do_focus = frame->isFocused();
209 }
210 }
211
212 // Not startup, pekwm (re)start it is.
213 } else {
214 long id;
215 if (AtomUtil::getLong(_window, Atoms::getAtom(PEKWM_FRAME_ID), id)) {
216 do_autogroup = false;
217 _parent = Frame::findFrameFromID(id);
218 if (_parent) {
219 Frame *frame = static_cast<Frame*>(_parent);
220 frame->addChildOrdered(this);
221 if (is_active) {
222 frame->activateChild(this);
223 }
224 do_focus = frame->isFocused();
225 }
226 }
227 }
228
229
230 // Apply Autoproperties again to override EWMH state. It's done twice as
231 // we need the cfg_deny property when reading the EWMH state.
232 if (ap) {
233 applyAutoprops(ap);
234
235 if (do_autogroup && ! _parent && (ap->group_size >= 0)) {
236 Frame* frame = WindowManager::instance()->findGroup(ap);
237 if (frame) {
238 frame->addChild(this);
239
240 if (! ap->group_behind) {
241 frame->activateChild(this);
242 do_focus = frame->isFocused();
243 }
244 if (ap->group_raise) {
245 frame->raise();
246 }
247 }
248 }
249 }
250
219 // Tell the world about our state
220 updateEwmhStates();
221
222 PScreen::instance()->ungrabServer(true);
223
256 // if we don't have a frame already, create a new one
257 if (! _parent) {
258 _parent = new Frame(this, ap);
259 }
260
261 // Make sure the window is mapped, this is done after it has been
262 // added to the decor/frame as otherwise IsViewable state won't
263 // be correct and we don't know whether or not to place the window
264 if (! _iconified) {
265 PWinObj::mapWindow();
266 }
267
268 // Let us hear what autoproperties has to say about focusing
269 if (is_new && ap && ap->isMask(AP_FOCUS_NEW)) {
270 do_focus = ap->focus_new;
271 }
272
273 // Only can give input focus to mapped windows
274 if (_parent->isMapped()) {
275 // Ordinary focus
276 if (do_focus) {
277 _parent->giveInputFocus();
278
279 // Check if we are transient, and if we want to focus
280 } else if ((_transient != None)
281 && Config::instance()->isFocusNewChild()) {
282 Client *trans_for = findClientFromWindow(_transient);
283 if (trans_for && trans_for->isFocused()) {
284 _parent->giveInputFocus();
285 }
286 }
287 }
256 setMappedStateAndFocus(is_new, ap);
257
258 _alive = true;
259
...  
206 @@ -362,6 +206,198 @@
206 PScreen::instance()->ungrabServer(true);
207 }
208
209 /**
210 * Read basic window attributes including geometry and update the
211 * window attributes being listened to. Returns false if the client
212 * disappears during the check.
213 */
214 bool
215 Client::getAndUpdateWindowAttributes(void)
216 {
217 XWindowAttributes attr;
218 if (! XGetWindowAttributes(_dpy, _window, &attr)) {
219 return false;
220 }
221 _gm.x = attr.x;
222 _gm.y = attr.y;
223 _gm.width = attr.width;
224 _gm.height = attr.height;
225
226 _cmap = attr.colormap;
227 _size = XAllocSizeHints();
228
229 XSetWindowAttributes sattr;
230 sattr.event_mask =
231 PropertyChangeMask|StructureNotifyMask|FocusChangeMask;
232 sattr.do_not_propagate_mask =
233 ButtonPressMask|ButtonReleaseMask|ButtonMotionMask;
234
235 // We don't want these masks to be propagated down to the frame
236 XChangeWindowAttributes(_dpy, _window, CWEventMask|CWDontPropagate, &sattr);
237
238 return true;
239 }
240
241 /**
242 * Find frame for client based on tagging, hints and
243 * autoproperties. Create a new one if not found and add the client.
244 */
245 void
246 Client::findOrCreateFrame(AutoProperty *autoproperty)
247 {
248 if (! _parent) {
249 findTaggedFrame();
250 }
251 if (! _parent) {
252 findPreviousFrame();
253 }
254
255 // Apply Autoproperties again to override EWMH state. It's done twice as
256 // we need the cfg_deny property when reading the EWMH state.
257 if (autoproperty != 0) {
258 applyAutoprops(autoproperty);
259 if (! _parent) {
260 findAutoGroupFrame(autoproperty);
261 }
262 }
263
264 // if we don't have a frame already, create a new one
265 if (! _parent) {
266 _parent = new Frame(this, autoproperty);
267 }
268 }
269
270 /**
271 * Find from client from for the currently tagged client.
272 */
273 bool
274 Client::findTaggedFrame(void)
275 {
276 if (! WindowManager::instance()->isStartup()) {
277 return false;
278 }
279
280 // Check for tagged frame
281 Frame *frame = Frame::getTagFrame();
282 if (frame && frame->isMapped()) {
283 _parent = frame;
284 frame->addChild(this);
285
286 if (! Frame::getTagBehind()) {
287 frame->activateChild(this);
288 }
289 }
290
291 return _parent != 0;
292 }
293
294 /**
295 * Find frame for client on PEKWM_FRAME_ID hint.
296 */
297 bool
298 Client::findPreviousFrame(void)
299 {
300 if (WindowManager::instance()->isStartup()) {
301 return false;
302 }
303
304 long id;
305 if (! AtomUtil::getLong(_window, Atoms::getAtom(PEKWM_FRAME_ID), id)) {
306 _parent = Frame::findFrameFromID(id);
307 if (_parent) {
308 Frame *frame = static_cast<Frame*>(_parent);
309 frame->addChildOrdered(this);
310 if (getPekwmFrameActive()) {
311 frame->activateChild(this);
312 }
313 }
314 }
315
316 return _parent != 0;
317 }
318
319 /**
320 * Find frame for client based on autoproperties.
321 */
322 bool
323 Client::findAutoGroupFrame(AutoProperty *autoproperty)
324 {
325 if (autoproperty->group_size < 0) {
326 return false;
327 }
328
329 Frame* frame = WindowManager::instance()->findGroup(autoproperty);
330 if (frame) {
331 frame->addChild(this);
332
333 if (! autoproperty->group_behind) {
334 frame->activateChild(this);
335 }
336 if (autoproperty->group_raise) {
337 frame->raise();
338 }
339 }
340
341 return _parent != 0;
342 }
343
344 /**
345 * Get the client state and set iconified and mapped flags.
346 */
347 void
348 Client::setInitialState(void)
349 {
350 // Set state either specified in hint
351 ulong initial_state = readWmHints();
352 if (getWmState() == IconicState) {
353 _iconified = true;
354 }
355
356 if (_iconified || initial_state == IconicState) {
357 _iconified = true;
358 _mapped = true;
359 unmapWindow();
360 } else {
361 setWmState(initial_state);
362 }
363 }
364
365 /**
366 * Ensure the Client is (un) mapped and give input focus if requested.
367 */
368 void
369 Client::setMappedStateAndFocus(bool is_new, AutoProperty *autoproperty)
370 {
371 // Make sure the window is mapped, this is done after it has been
372 // added to the decor/frame as otherwise IsViewable state won't
373 // be correct and we don't know whether or not to place the window
374 if (! _iconified) {
375 PWinObj::mapWindow();
376 }
377
378 // Let us hear what autoproperties has to say about focusing
379 bool do_focus = is_new ? Config::instance()->isFocusNew() : false;
380 if (is_new && autoproperty && autoproperty->isMask(AP_FOCUS_NEW)) {
381 do_focus = autoproperty->focus_new;
382 }
383
384 // Only can give input focus to mapped windows
385 if (_parent->isMapped()) {
386 // Ordinary focus
387 if (do_focus) {
388 _parent->giveInputFocus();
389
390 // Check if we are transient, and if we want to focus
391 } else if ((_transient != None)
392 && Config::instance()->isFocusNewChild()) {
393 Client *trans_for = findClientFromWindow(_transient);
394 if (trans_for && trans_for->isFocused()) {
395 _parent->giveInputFocus();
396 }
397 }
398 }
399 }
400
401 // START - PWinObj interface.
402
403 //! @brief Maps the window.
...  
739 @@ -703,6 +739,46 @@
739 }
740
741 /**
742 * Read "all" hints required during creation of Client.
743 */
744 void
745 Client::readHints(void)
746 {
747 getTransientForHint();
748 readMwmHints(); // read atoms
749 readEwmhHints();
750 readPekwmHints();
751 readIcon();
752 readClientPid();
753 readClientRemote();
754 getWMProtocols();
755 }
756
757 /**
758 * Read WM Hints, return the initial state of the window.
759 */
760 ulong
761 Client::readWmHints(void)
762 {
763 ulong initial_state = NormalState;
764 XWMHints* hints = XGetWMHints(_dpy, _window);
765 if (hints) {
766 // get the input focus mode
767 if (hints->flags&InputHint) { // FIXME: More logic needed
768 _wm_hints_input = hints->input;
769 }
770
771 // Get initial state of the window
772 if (hints->flags&StateHint) {
773 initial_state = hints->initial_state;
774 }
775
776 XFree(hints);
777 }
778 return initial_state;
779 }
780
781 /**
782 * Read the WM_CLASS hint and set information on the _class_hint used
783 * in matching auto properties.
784 */
...