Merge lp:~compiz-team/compiz-core/compiz-core.fix_853734 into lp:compiz-core/0.9.5
- compiz-core.fix_853734
- Merge into 0.9.5
Proposed by
Sam Spilsbury
Status: | Merged |
---|---|
Merged at revision: | 2827 |
Proposed branch: | lp:~compiz-team/compiz-core/compiz-core.fix_853734 |
Merge into: | lp:compiz-core/0.9.5 |
Diff against target: |
501 lines (+204/-53) (has conflicts) 3 files modified
src/privatewindow.h (+1/-0) src/window.cpp (+195/-45) src/windowgeometry.cpp (+8/-8) Text conflict in src/window.cpp |
To merge this branch: | bzr merge lp:~compiz-team/compiz-core/compiz-core.fix_853734 |
Related bugs: |
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
Compiz Maintainers | Pending | ||
Review via email: mp+76020@code.launchpad.net |
This proposal supersedes a proposal from 2011-09-19.
Commit message
Description of the change
Ensure that we update frame regions correctly by doing the following:
* Only update frame regions when we get an event that something changed
server side (eg don't immediately update the region once we issue
a ConfigureWindow request)
* Keep track of the changes in the input extents
* Ensure that a synthetic ConfigureNotify is sent in cases where the resized
frame window will exactly match its last size such that the client is
positioned correctly inside the frame
To post a comment you must log in.
Revision history for this message
Mirco Müller (macslow) wrote : Posted in a previous version of this proposal | # |
Revision history for this message
Mikkel Kamstrup Erlandsen (kamstrup) wrote : Posted in a previous version of this proposal | # |
I can confirm that maximize->minimize works fine here. And generally everything seems to work fine. Haven't had time to do code review.
Preview Diff
[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1 | === modified file 'src/privatewindow.h' |
2 | --- src/privatewindow.h 2011-09-19 12:35:49 +0000 |
3 | +++ src/privatewindow.h 2011-09-19 12:54:14 +0000 |
4 | @@ -296,6 +296,7 @@ |
5 | bool alive; |
6 | |
7 | CompWindowExtents input; |
8 | + CompWindowExtents serverInput; |
9 | CompWindowExtents border; |
10 | CompWindowExtents output; |
11 | |
12 | |
13 | === modified file 'src/window.cpp' |
14 | --- src/window.cpp 2011-09-19 12:35:49 +0000 |
15 | +++ src/window.cpp 2011-09-19 12:54:14 +0000 |
16 | @@ -795,20 +795,24 @@ |
17 | if (!serverFrame) |
18 | return; |
19 | |
20 | +<<<<<<< TREE |
21 | gettimeofday (&lastConfigureRequest, NULL); |
22 | |
23 | if (input.left || input.right || input.top || input.bottom) |
24 | +======= |
25 | + if (serverInput.left || serverInput.right || serverInput.top || serverInput.bottom) |
26 | +>>>>>>> MERGE-SOURCE |
27 | { |
28 | int x, y, width, height; |
29 | int bw = serverGeometry.border () * 2; |
30 | |
31 | - x = serverGeometry.x () - input.left; |
32 | - y = serverGeometry.y () - input.top; |
33 | - width = serverGeometry.width () + input.left + input.right + bw; |
34 | - height = serverGeometry.height () + input.top + input.bottom + bw; |
35 | + x = serverGeometry.x () - serverInput.left; |
36 | + y = serverGeometry.y () - serverInput.top; |
37 | + width = serverGeometry.width () + serverInput.left + serverInput.right + bw; |
38 | + height = serverGeometry.height () + serverInput.top + serverInput.bottom + bw; |
39 | |
40 | if (shaded) |
41 | - height = input.top + input.bottom; |
42 | + height = serverInput.top + serverInput.bottom; |
43 | |
44 | /* Geometry is the same, so we're not going to get a ConfigureNotify |
45 | * event when the window is configured, which means that other plugins |
46 | @@ -821,9 +825,9 @@ |
47 | { |
48 | XConfigureEvent xev; |
49 | XWindowAttributes attrib; |
50 | - unsigned int nchildren; |
51 | - Window rootRet, parentRet; |
52 | - Window *children; |
53 | + unsigned int nchildren = 0; |
54 | + Window rootRet = 0, parentRet = 0; |
55 | + Window *children = NULL; |
56 | |
57 | xev.type = ConfigureNotify; |
58 | xev.event = screen->root (); |
59 | @@ -885,14 +889,12 @@ |
60 | else |
61 | { |
62 | XMapWindow (screen->dpy (), wrapper); |
63 | - XMoveResizeWindow (screen->dpy (), wrapper, input.left, input.top, |
64 | + XMoveResizeWindow (screen->dpy (), wrapper, serverInput.left, serverInput.top, |
65 | serverGeometry.width (), serverGeometry.height ()); |
66 | } |
67 | - XMoveResizeWindow (screen->dpy (), id, 0, 0, |
68 | + XMoveResizeWindow (screen->dpy (), id, 0, 0, |
69 | serverGeometry.width (), serverGeometry.height ()); |
70 | - window->sendConfigureNotify (); |
71 | - |
72 | - window->updateFrameRegion (); |
73 | + window->sendConfigureNotify (); |
74 | window->windowNotify (CompWindowNotifyFrameUpdate); |
75 | } |
76 | else |
77 | @@ -908,7 +910,74 @@ |
78 | if (shaded) |
79 | height = 0; |
80 | |
81 | - XMoveResizeWindow (screen->dpy (), serverFrame, x, y, width, height); |
82 | + /* Geometry is the same, so we're not going to get a ConfigureNotify |
83 | + * event when the window is configured, which means that other plugins |
84 | + * won't know that the client, frame and wrapper windows got shifted |
85 | + * around (and might result in display corruption, eg in OpenGL */ |
86 | + if (geometry.x () - input.left == x && |
87 | + geometry.y () - input.top == y && |
88 | + geometry.width () + input.left + input.right + bw == width && |
89 | + geometry.height () + input.top + input.bottom + bw == height) |
90 | + { |
91 | + XConfigureEvent xev; |
92 | + XWindowAttributes attrib; |
93 | + unsigned int nchildren = 0; |
94 | + Window rootRet = 0, parentRet = 0; |
95 | + Window *children = NULL; |
96 | + |
97 | + xev.type = ConfigureNotify; |
98 | + xev.event = screen->root (); |
99 | + xev.window = priv->serverFrame; |
100 | + |
101 | + XGrabServer (screen->dpy ()); |
102 | + |
103 | + if (XGetWindowAttributes (screen->dpy (), priv->serverFrame, &attrib)) |
104 | + { |
105 | + xev.x = attrib.x; |
106 | + xev.y = attrib.y; |
107 | + xev.width = attrib.width; |
108 | + xev.height = attrib.height; |
109 | + xev.border_width = attrib.border_width; |
110 | + xev.above = None; |
111 | + |
112 | + /* We need to ensure that the stacking order is |
113 | + * based on the current server stacking order so |
114 | + * find the sibling to this window's frame in the |
115 | + * server side stack and stack above that */ |
116 | + XQueryTree (screen->dpy (), screen->root (), &rootRet, &parentRet, &children, &nchildren); |
117 | + |
118 | + if (nchildren) |
119 | + { |
120 | + for (unsigned int i = 0; i < nchildren; i++) |
121 | + { |
122 | + if (i + 1 == nchildren || |
123 | + children[i + 1] == ROOTPARENT (window)) |
124 | + { |
125 | + xev.above = children[i]; |
126 | + break; |
127 | + } |
128 | + } |
129 | + } |
130 | + |
131 | + if (children) |
132 | + XFree (children); |
133 | + |
134 | + if (!xev.above) |
135 | + xev.above = (window->serverPrev) ? ROOTPARENT (window->serverPrev) : None; |
136 | + |
137 | + xev.override_redirect = priv->attrib.override_redirect; |
138 | + |
139 | + } |
140 | + |
141 | + XSendEvent (screen->dpy (), screen->root (), false, |
142 | + SubstructureNotifyMask, (XEvent *) &xev); |
143 | + |
144 | + XUngrabServer (screen->dpy ()); |
145 | + XSync (screen->dpy (), false); |
146 | + } |
147 | + else |
148 | + XMoveResizeWindow (screen->dpy (), serverFrame, x, y, width, height); |
149 | + |
150 | if (shaded) |
151 | { |
152 | XUnmapWindow (screen->dpy (), wrapper); |
153 | @@ -920,10 +989,9 @@ |
154 | serverGeometry.width (), serverGeometry.height ()); |
155 | } |
156 | |
157 | - XMoveResizeWindow (screen->dpy (), id, 0, 0, |
158 | + XMoveResizeWindow (screen->dpy (), id, 0, 0, |
159 | serverGeometry.width (), serverGeometry.height ()); |
160 | - window->sendConfigureNotify (); |
161 | - frameRegion = CompRegion (); |
162 | + window->sendConfigureNotify (); |
163 | window->windowNotify (CompWindowNotifyFrameUpdate); |
164 | } |
165 | window->recalcActions (); |
166 | @@ -1384,6 +1452,7 @@ |
167 | * server configuration */ |
168 | |
169 | XGrabServer (screen->dpy ()); |
170 | + XSync (screen->dpy (), false); |
171 | |
172 | if (XGetWindowAttributes (screen->dpy (), priv->id, &attrib)) |
173 | { |
174 | @@ -1659,6 +1728,17 @@ |
175 | bool |
176 | CompWindow::resize (CompWindow::Geometry gm) |
177 | { |
178 | + /* Input extents are now the last thing sent |
179 | + * from the server. This might not work in some |
180 | + * cases though because setWindowFrameExtents may |
181 | + * be called more than once in an event processing |
182 | + * cycle so every set of input extents up until the |
183 | + * last one will be invalid. The real solution |
184 | + * here is to handle ConfigureNotify events on |
185 | + * frame windows and client windows separately */ |
186 | + |
187 | + priv->input = priv->serverInput; |
188 | + |
189 | if (priv->geometry.width () != gm.width () || |
190 | priv->geometry.height () != gm.height () || |
191 | priv->geometry.border () != gm.border ()) |
192 | @@ -1692,7 +1772,6 @@ |
193 | resizeNotify (dx, dy, dwidth, dheight); |
194 | |
195 | priv->invisible = WINDOW_INVISIBLE (priv); |
196 | - priv->updateFrameWindow (); |
197 | } |
198 | else if (priv->geometry.x () != gm.x () || priv->geometry.y () != gm.y ()) |
199 | { |
200 | @@ -1710,6 +1789,8 @@ |
201 | move (dx, dy); |
202 | } |
203 | |
204 | + updateFrameRegion (); |
205 | + |
206 | return true; |
207 | } |
208 | |
209 | @@ -1866,10 +1947,15 @@ |
210 | if (!priv->frame) |
211 | return; |
212 | |
213 | - x = ce->x + priv->input.left; |
214 | - y = ce->y + priv->input.top; |
215 | - width = ce->width - priv->serverGeometry.border () * 2 - priv->input.left - priv->input.right; |
216 | - height = ce->height - priv->serverGeometry.border () * 2 - priv->input.top - priv->input.bottom; |
217 | + /* subtract the input extents last sent to the |
218 | + * server to calculate the client size and then |
219 | + * re-sync the input extents and extents last |
220 | + * sent to server on resize () */ |
221 | + |
222 | + x = ce->x + priv->serverInput.left; |
223 | + y = ce->y + priv->serverInput.top; |
224 | + width = ce->width - priv->serverGeometry.border () * 2 - priv->serverInput.left - priv->serverInput.right; |
225 | + height = ce->height - priv->serverGeometry.border () * 2 - priv->serverInput.top - priv->serverInput.bottom; |
226 | |
227 | if (priv->syncWait) |
228 | { |
229 | @@ -1943,13 +2029,13 @@ |
230 | gettimeofday (&priv->lastConfigureRequest, NULL); |
231 | |
232 | XMoveWindow (screen->dpy (), ROOTPARENT (this), |
233 | - priv->geometry.x () - priv->input.left, |
234 | - priv->geometry.y () - priv->input.top); |
235 | + priv->serverGeometry.x () - priv->serverInput.left, |
236 | + priv->serverGeometry.y () - priv->serverInput.top); |
237 | |
238 | if (priv->serverFrame) |
239 | { |
240 | XMoveWindow (screen->dpy (), priv->wrapper, |
241 | - priv->input.left, priv->input.top); |
242 | + priv->serverInput.left, priv->serverInput.top); |
243 | sendConfigureNotify (); |
244 | } |
245 | } |
246 | @@ -2706,22 +2792,31 @@ |
247 | { |
248 | XWindowChanges wc = *xwc; |
249 | |
250 | +<<<<<<< TREE |
251 | gettimeofday (&lastConfigureRequest, NULL); |
252 | |
253 | wc.x -= input.left - serverGeometry.border (); |
254 | wc.y -= input.top - serverGeometry.border (); |
255 | wc.width += input.left + input.right + serverGeometry.border (); |
256 | wc.height += input.top + input.bottom + serverGeometry.border (); |
257 | +======= |
258 | + wc.x -= serverInput.left - serverGeometry.border (); |
259 | + wc.y -= serverInput.top - serverGeometry.border (); |
260 | + wc.width += serverInput.left + serverInput.right + serverGeometry.border (); |
261 | + wc.height += serverInput.top + serverInput.bottom + serverGeometry.border (); |
262 | +>>>>>>> MERGE-SOURCE |
263 | |
264 | XConfigureWindow (screen->dpy (), serverFrame, valueMask, &wc); |
265 | valueMask &= ~(CWSibling | CWStackMode); |
266 | |
267 | - xwc->x = input.left; |
268 | - xwc->y = input.top; |
269 | + xwc->x = serverInput.left; |
270 | + xwc->y = serverInput.top; |
271 | XConfigureWindow (screen->dpy (), wrapper, valueMask, xwc); |
272 | |
273 | xwc->x = 0; |
274 | xwc->y = 0; |
275 | + |
276 | + window->sendConfigureNotify (); |
277 | } |
278 | |
279 | XConfigureWindow (screen->dpy (), id, valueMask, xwc); |
280 | @@ -3076,8 +3171,8 @@ |
281 | { |
282 | saveGeometry (CWY | CWHeight); |
283 | |
284 | - xwc->height = workArea.height () - input.top - |
285 | - input.bottom - old.border () * 2; |
286 | + xwc->height = workArea.height () - serverInput.top - |
287 | + serverInput.bottom - old.border () * 2; |
288 | |
289 | mask |= CWHeight; |
290 | } |
291 | @@ -3090,8 +3185,8 @@ |
292 | { |
293 | saveGeometry (CWX | CWWidth); |
294 | |
295 | - xwc->width = workArea.width () - input.left - |
296 | - input.right - old.border () * 2; |
297 | + xwc->width = workArea.width () - serverInput.left - |
298 | + serverInput.right - old.border () * 2; |
299 | |
300 | mask |= CWWidth; |
301 | } |
302 | @@ -3158,6 +3253,7 @@ |
303 | |
304 | if (state & CompWindowStateMaximizedVertMask) |
305 | { |
306 | +<<<<<<< TREE |
307 | /* If the window is still offscreen, then we need to constrain it |
308 | * by the gravity value (so that the corner that the gravity specifies |
309 | * is 'anchored' to that edge of the workarea) */ |
310 | @@ -3194,11 +3290,36 @@ |
311 | default: |
312 | /* Shift the window so that the top meets the top of the screen */ |
313 | break; |
314 | +======= |
315 | + if (old.y () < y + workArea.y () + serverInput.top) |
316 | + { |
317 | + xwc->y = y + workArea.y () + serverInput.top; |
318 | + mask |= CWY; |
319 | + } |
320 | + else |
321 | + { |
322 | + height = xwc->height + old.border () * 2; |
323 | + |
324 | + max = y + workArea.bottom (); |
325 | + if (old.y () + (int) old.height () + serverInput.bottom > max) |
326 | + { |
327 | + xwc->y = max - height - serverInput.bottom; |
328 | + mask |= CWY; |
329 | + } |
330 | + else if (old.y () + height + serverInput.bottom > max) |
331 | + { |
332 | + xwc->y = y + workArea.y () + |
333 | + (workArea.height () - serverInput.top - height - |
334 | + serverInput.bottom) / 2 + serverInput.top; |
335 | + mask |= CWY; |
336 | + } |
337 | +>>>>>>> MERGE-SOURCE |
338 | } |
339 | } |
340 | |
341 | if (state & CompWindowStateMaximizedHorzMask) |
342 | { |
343 | +<<<<<<< TREE |
344 | xwc->x = x + workArea.x () + input.left; |
345 | mask |= CWX; |
346 | |
347 | @@ -3235,6 +3356,30 @@ |
348 | case WestGravity: |
349 | default: |
350 | break; |
351 | +======= |
352 | + if (old.x () < x + workArea.x () + serverInput.left) |
353 | + { |
354 | + xwc->x = x + workArea.x () + serverInput.left; |
355 | + mask |= CWX; |
356 | + } |
357 | + else |
358 | + { |
359 | + width = xwc->width + old.border () * 2; |
360 | + |
361 | + max = x + workArea.right (); |
362 | + if (old.x () + (int) old.width () + serverInput.right > max) |
363 | + { |
364 | + xwc->x = max - width - serverInput.right; |
365 | + mask |= CWX; |
366 | + } |
367 | + else if (old.x () + width + serverInput.right > max) |
368 | + { |
369 | + xwc->x = x + workArea.x () + |
370 | + (workArea.width () - serverInput.left - width - |
371 | + serverInput.right) / 2 + serverInput.left; |
372 | + mask |= CWX; |
373 | + } |
374 | +>>>>>>> MERGE-SOURCE |
375 | } |
376 | } |
377 | } |
378 | @@ -3309,15 +3454,15 @@ |
379 | case NorthGravity: |
380 | case NorthEastGravity: |
381 | if (xwcm & CWY) |
382 | - newY = xwc->y + priv->input.top * direction; |
383 | + newY = xwc->y + priv->serverInput.top * direction; |
384 | break; |
385 | |
386 | case WestGravity: |
387 | case CenterGravity: |
388 | case EastGravity: |
389 | if (xwcm & CWY) |
390 | - newY -= (xwc->height / 2 - priv->input.top + |
391 | - (priv->input.top + priv->input.bottom) / 2) * direction; |
392 | + newY -= (xwc->height / 2 - priv->serverInput.top + |
393 | + (priv->serverInput.top + priv->serverInput.bottom) / 2) * direction; |
394 | else |
395 | newY -= ((xwc->height - priv->serverGeometry.height ()) / 2) * direction; |
396 | break; |
397 | @@ -3326,7 +3471,7 @@ |
398 | case SouthGravity: |
399 | case SouthEastGravity: |
400 | if (xwcm & CWY) |
401 | - newY -= xwc->height + priv->input.bottom * direction; |
402 | + newY -= xwc->height + priv->serverInput.bottom * direction; |
403 | else |
404 | newY -= (xwc->height - priv->serverGeometry.height ()) * direction; |
405 | break; |
406 | @@ -3791,14 +3936,14 @@ |
407 | y2 = y1 + screen->workArea ().height () + screen->vpSize ().height () * |
408 | screen->height (); |
409 | |
410 | - if (serverGeometry.x () - input.left >= x2) |
411 | + if (serverGeometry.x () - serverInput.left >= x2) |
412 | dx = (x2 - 25) - serverGeometry.x (); |
413 | - else if (serverGeometry.x () + width + input.right <= x1) |
414 | + else if (serverGeometry.x () + width + serverInput.right <= x1) |
415 | dx = (x1 + 25) - (serverGeometry.x () + width); |
416 | |
417 | - if (serverGeometry.y () - input.top >= y2) |
418 | + if (serverGeometry.y () - serverInput.top >= y2) |
419 | dy = (y2 - 25) - serverGeometry.y (); |
420 | - else if (serverGeometry.y () + height + input.bottom <= y1) |
421 | + else if (serverGeometry.y () + height + serverInput.bottom <= y1) |
422 | dy = (y1 + 25) - (serverGeometry.y () + height); |
423 | |
424 | if (dx || dy) |
425 | @@ -5456,7 +5601,7 @@ |
426 | CompWindowExtents & |
427 | CompWindow::input () const |
428 | { |
429 | - return priv->input; |
430 | + return priv->serverInput; |
431 | } |
432 | |
433 | CompWindowExtents & |
434 | @@ -5929,6 +6074,11 @@ |
435 | input.top = 0; |
436 | input.bottom = 0; |
437 | |
438 | + serverInput.left = 0; |
439 | + serverInput.right = 0; |
440 | + serverInput.top = 0; |
441 | + serverInput.bottom = 0; |
442 | + |
443 | border.top = 0; |
444 | border.bottom = 0; |
445 | border.left = 0; |
446 | @@ -6122,14 +6272,14 @@ |
447 | if (!i) |
448 | i = b; |
449 | |
450 | - if (priv->input.left != i->left || |
451 | - priv->input.right != i->right || |
452 | - priv->input.top != i->top || |
453 | - priv->input.bottom != i->bottom) |
454 | + if (priv->serverInput.left != i->left || |
455 | + priv->serverInput.right != i->right || |
456 | + priv->serverInput.top != i->top || |
457 | + priv->serverInput.bottom != i->bottom) |
458 | { |
459 | unsigned long data[4]; |
460 | |
461 | - priv->input = *i; |
462 | + priv->serverInput = *i; |
463 | priv->border = *b; |
464 | |
465 | recalcActions (); |
466 | |
467 | === modified file 'src/windowgeometry.cpp' |
468 | --- src/windowgeometry.cpp 2011-04-30 13:40:41 +0000 |
469 | +++ src/windowgeometry.cpp 2011-09-19 12:54:14 +0000 |
470 | @@ -189,23 +189,23 @@ |
471 | CompRect |
472 | CompWindow::inputRect () const |
473 | { |
474 | - return CompRect (priv->geometry.x () - priv->geometry.border () - priv->input.left, |
475 | - priv->geometry.y () - priv->geometry.border () - priv->input.top, |
476 | + return CompRect (priv->geometry.x () - priv->geometry.border () - priv->serverInput.left, |
477 | + priv->geometry.y () - priv->geometry.border () - priv->serverInput.top, |
478 | priv->geometry.width () + priv->geometry.border () * 2 + |
479 | - priv->input.left + priv->input.right, |
480 | + priv->serverInput.left + priv->serverInput.right, |
481 | priv->geometry.height () +priv->geometry.border () * 2 + |
482 | - priv->input.top + priv->input.bottom); |
483 | + priv->serverInput.top + priv->serverInput.bottom); |
484 | } |
485 | |
486 | CompRect |
487 | CompWindow::serverInputRect () const |
488 | { |
489 | - return CompRect (priv->serverGeometry.x () - priv->serverGeometry.border () - priv->input.left, |
490 | - priv->serverGeometry.y () - priv->serverGeometry.border () - priv->input.top, |
491 | + return CompRect (priv->serverGeometry.x () - priv->serverGeometry.border () - priv->serverInput.left, |
492 | + priv->serverGeometry.y () - priv->serverGeometry.border () - priv->serverInput.top, |
493 | priv->serverGeometry.width () + priv->serverGeometry.border () * 2 + |
494 | - priv->input.left + priv->input.right, |
495 | + priv->serverInput.left + priv->serverInput.right, |
496 | priv->serverGeometry.height () + priv->serverGeometry.border () * 2 + |
497 | - priv->input.top + priv->input.bottom); |
498 | + priv->serverInput.top + priv->serverInput.bottom); |
499 | } |
500 | |
501 | CompRect |
I'm not able to compile compiz here atm. But what I suggest is to initialize all declared variables.