Merge lp:~smspillaz/compiz-core/compiz-core.tests_915950 into lp:compiz-core/0.9.5
- compiz-core.tests_915950
- Merge into 0.9.5
Status: | Merged |
---|---|
Merged at revision: | 2979 |
Proposed branch: | lp:~smspillaz/compiz-core/compiz-core.tests_915950 |
Merge into: | lp:compiz-core/0.9.5 |
Diff against target: |
1328 lines (+749/-285) 9 files modified
plugins/place/CMakeLists.txt (+4/-1) plugins/place/src/place.cpp (+126/-280) plugins/place/src/place.h (+8/-4) plugins/place/src/smart/CMakeLists.txt (+62/-0) plugins/place/src/smart/include/smart.h (+73/-0) plugins/place/src/smart/src/smart.cpp (+199/-0) plugins/place/src/smart/tests/CMakeLists.txt (+14/-0) plugins/place/src/smart/tests/offscreen/src/test-place-smart-on-screen.cpp (+156/-0) plugins/place/src/smart/tests/offscreen/src/test-place-smart-onscren.cpp (+107/-0) |
To merge this branch: | bzr merge lp:~smspillaz/compiz-core/compiz-core.tests_915950 |
Related bugs: |
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
Sam Spilsbury | Approve | ||
Alan Griffiths | Approve | ||
Review via email: mp+90751@code.launchpad.net |
Commit message
Description of the change
Tests that smart placement does not put windows offscreen on two different sized monitors
Sam Spilsbury (smspillaz) wrote : | # |
Or rather, there's a useless file here.
Daniel van Vugt (vanvugt) wrote : | # |
Maybe it's just me, but I'm concerned about the amount of core code being rewritten here (and wasn't reviewed). If it were up to me I wouldn't modify so much core code so close to release. I don't think all the changes are relevant to writing test cases either.
Daniel van Vugt (vanvugt) wrote : | # |
Sam reverted the merge. Needs review again.
Sam Spilsbury (smspillaz) wrote : | # |
Code was unintentionally pushed to trunk. thats now reverted.
As for this change - all it does is add an interface for a placeable object. the diff is large because things moved around etc
Alan Griffiths (alan-griffiths) wrote : | # |
This *looks* OK, but like Daniel says it looks like several (sequential) changes overlayed on each other which makes it hard to validate.
I'd prefer to see separate commits for refactoring (moving/renaming stuff) and functional changes (making it work). (But I'm as guilty of mixing the two.)
Sam Spilsbury (smspillaz) : | # |
Preview Diff
1 | === modified file 'plugins/place/CMakeLists.txt' |
2 | --- plugins/place/CMakeLists.txt 2012-01-20 06:27:10 +0000 |
3 | +++ plugins/place/CMakeLists.txt 2012-01-30 18:23:23 +0000 |
4 | @@ -4,7 +4,10 @@ |
5 | |
6 | include_directories (${CMAKE_CURRENT_SOURCE_DIR}/src/constrain-to-workarea/include/) |
7 | include_directories (${CMAKE_CURRENT_SOURCE_DIR}/src/screen-size-change/include/) |
8 | +include_directories (${CMAKE_CURRENT_SOURCE_DIR}/src/smart/include/) |
9 | |
10 | add_subdirectory (src/constrain-to-workarea) |
11 | add_subdirectory (src/screen-size-change) |
12 | -compiz_plugin (place LIBRARIES compiz_place_constrain_to_workarea compiz_place_screen_size_change) |
13 | +add_subdirectory (src/smart) |
14 | + |
15 | +compiz_plugin (place LIBRARIES compiz_place_constrain_to_workarea compiz_place_screen_size_change compiz_place_smart) |
16 | |
17 | === modified file 'plugins/place/src/place.cpp' |
18 | --- plugins/place/src/place.cpp 2012-01-25 09:20:47 +0000 |
19 | +++ plugins/place/src/place.cpp 2012-01-30 18:23:23 +0000 |
20 | @@ -65,7 +65,6 @@ |
21 | return l; |
22 | } |
23 | |
24 | - |
25 | void |
26 | PlaceScreen::doHandleScreenSizeChange (int newWidth, |
27 | int newHeight) |
28 | @@ -101,12 +100,31 @@ |
29 | return screen->getWorkareaForOutput (screen->outputDeviceForGeometry (g)); |
30 | } |
31 | |
32 | +const CompRect & |
33 | +PlaceWindow::getWorkarea () const |
34 | +{ |
35 | + return getWorkarea (window->serverGeometry ()); |
36 | +} |
37 | + |
38 | const compiz::window::extents::Extents & |
39 | PlaceWindow::getExtents () const |
40 | { |
41 | return window->border (); |
42 | } |
43 | |
44 | +unsigned int |
45 | +PlaceWindow::getState () const |
46 | +{ |
47 | + unsigned int state = 0; |
48 | + |
49 | + if (window->state () & CompWindowStateAboveMask) |
50 | + state |= compiz::place::WindowAbove; |
51 | + if (window->state () & CompWindowStateBelowMask) |
52 | + state |= compiz::place::WindowBelow; |
53 | + |
54 | + return state; |
55 | +} |
56 | + |
57 | void |
58 | PlaceWindow::applyGeometry (compiz::window::Geometry &ng, |
59 | compiz::window::Geometry &og) |
60 | @@ -224,42 +242,42 @@ |
61 | /* sort functions */ |
62 | |
63 | static bool |
64 | -compareLeftmost (CompWindow *a, |
65 | - CompWindow *b) |
66 | +compareLeftmost (compiz::place::Placeable *a, |
67 | + compiz::place::Placeable *b) |
68 | { |
69 | int ax, bx; |
70 | |
71 | - ax = a->serverX () - a->border ().left; |
72 | - bx = b->serverX () - b->border ().left; |
73 | + ax = a->geometry ().x () - a->extents ().left; |
74 | + bx = b->geometry ().x () - a->extents ().left; |
75 | |
76 | return (ax <= bx); |
77 | } |
78 | |
79 | static bool |
80 | -compareTopmost (CompWindow *a, |
81 | - CompWindow *b) |
82 | +compareTopmost (compiz::place::Placeable *a, |
83 | + compiz::place::Placeable *b) |
84 | { |
85 | int ay, by; |
86 | |
87 | - ay = a->serverY () - a->border ().top; |
88 | - by = b->serverY () - b->border ().top; |
89 | + ay = a->geometry ().y () - a->extents ().top; |
90 | + by = b->geometry ().y () - a->extents ().top; |
91 | |
92 | return (ay <= by); |
93 | } |
94 | |
95 | static bool |
96 | -compareNorthWestCorner (CompWindow *a, |
97 | - CompWindow *b) |
98 | +compareNorthWestCorner (compiz::place::Placeable *a, |
99 | + compiz::place::Placeable *b) |
100 | { |
101 | int fromOriginA; |
102 | int fromOriginB; |
103 | int ax, ay, bx, by; |
104 | |
105 | - ax = a->serverX () - a->border ().left; |
106 | - ay = a->serverY () - a->border ().top; |
107 | + ax = a->geometry ().x () - a->extents ().left; |
108 | + bx = b->geometry ().x () - a->extents ().left; |
109 | |
110 | - bx = b->serverX () - b->border ().left; |
111 | - by = b->serverY () - b->border ().top; |
112 | + ay = a->geometry ().y () - a->extents ().top; |
113 | + by = b->geometry ().y () - a->extents ().top; |
114 | |
115 | /* probably there's a fast good-enough-guess we could use here. */ |
116 | fromOriginA = sqrt (ax * ax + ay * ay); |
117 | @@ -585,6 +603,17 @@ |
118 | |
119 | if (strategy == PlaceOnly || strategy == PlaceAndConstrain) |
120 | { |
121 | + /* Construct list of placeables */ |
122 | + compiz::place::Placeable::Vector placeables; |
123 | + |
124 | + foreach (CompWindow *w, screen->windows ()) |
125 | + { |
126 | + PLACE_WINDOW (w); |
127 | + |
128 | + if (windowIsPlaceRelevant (w)) |
129 | + placeables.push_back (static_cast <compiz::place::Placeable *> (pw)); |
130 | + } |
131 | + |
132 | switch (mode) { |
133 | case PlaceOptions::ModeCascade: |
134 | placeCascade (workArea, pos); |
135 | @@ -602,7 +631,7 @@ |
136 | sendMaximizationRequest (); |
137 | break; |
138 | case PlaceOptions::ModeSmart: |
139 | - placeSmart (workArea, pos); |
140 | + placeSmart (pos, placeables); |
141 | break; |
142 | } |
143 | |
144 | @@ -650,7 +679,7 @@ |
145 | PlaceWindow::placeCascade (const CompRect &workArea, |
146 | CompPoint &pos) |
147 | { |
148 | - CompWindowList windows; |
149 | + Placeable::Vector placeables; |
150 | |
151 | /* Find windows that matter (not minimized, on same workspace |
152 | * as placed window, may be shaded - if shaded we pretend it isn't |
153 | @@ -671,15 +700,15 @@ |
154 | w->serverY () + w->serverGeometry ().height () <= workArea.y ()) |
155 | continue; |
156 | |
157 | - windows.push_back (w); |
158 | + placeables.push_back (static_cast <Placeable *> (PlaceWindow::get (w))); |
159 | } |
160 | |
161 | - if (!cascadeFindFirstFit (windows, workArea, pos)) |
162 | + if (!cascadeFindFirstFit (placeables, workArea, pos)) |
163 | { |
164 | /* if the window wasn't placed at the origin of screen, |
165 | * cascade it onto the current screen |
166 | */ |
167 | - cascadeFindNext (windows, workArea, pos); |
168 | + cascadeFindNext (placeables, workArea, pos); |
169 | } |
170 | } |
171 | |
172 | @@ -727,201 +756,13 @@ |
173 | placeCentered (workArea, pos); |
174 | } |
175 | |
176 | - |
177 | -/* overlap types */ |
178 | -#define NONE 0 |
179 | -#define H_WRONG -1 |
180 | -#define W_WRONG -2 |
181 | +using namespace compiz::place; |
182 | |
183 | void |
184 | -PlaceWindow::placeSmart (const CompRect &workArea, |
185 | - CompPoint &pos) |
186 | +PlaceWindow::placeSmart (CompPoint &pos, |
187 | + const compiz::place::Placeable::Vector &placeables) |
188 | { |
189 | - /* |
190 | - * SmartPlacement by Cristian Tibirna (tibirna@kde.org) |
191 | - * adapted for kwm (16-19jan98) and for kwin (16Nov1999) using (with |
192 | - * permission) ideas from fvwm, authored by |
193 | - * Anthony Martin (amartin@engr.csulb.edu). |
194 | - * Xinerama supported added by Balaji Ramani (balaji@yablibli.com) |
195 | - * with ideas from xfce. |
196 | - * adapted for Compiz by Bellegarde Cedric (gnumdk(at)gmail.com) |
197 | - */ |
198 | - int overlap, minOverlap = 0; |
199 | - int xOptimal, yOptimal; |
200 | - int possible; |
201 | - |
202 | - /* temp coords */ |
203 | - int cxl, cxr, cyt, cyb; |
204 | - /* temp coords */ |
205 | - int xl, xr, yt, yb; |
206 | - /* temp holder */ |
207 | - int basket; |
208 | - /* CT lame flag. Don't like it. What else would do? */ |
209 | - bool firstPass = true; |
210 | - |
211 | - /* get the maximum allowed windows space */ |
212 | - int xTmp = workArea.x (); |
213 | - int yTmp = workArea.y (); |
214 | - |
215 | - /* client gabarit */ |
216 | - int cw = window->serverWidth () - 1; |
217 | - int ch = window->serverHeight () - 1; |
218 | - |
219 | - xOptimal = xTmp; |
220 | - yOptimal = yTmp; |
221 | - |
222 | - /* loop over possible positions */ |
223 | - do |
224 | - { |
225 | - /* test if enough room in x and y directions */ |
226 | - if (yTmp + ch > workArea.bottom () && ch < workArea.height ()) |
227 | - overlap = H_WRONG; /* this throws the algorithm to an exit */ |
228 | - else if (xTmp + cw > workArea.right ()) |
229 | - overlap = W_WRONG; |
230 | - else |
231 | - { |
232 | - overlap = NONE; /* initialize */ |
233 | - |
234 | - cxl = xTmp; |
235 | - cxr = xTmp + cw; |
236 | - cyt = yTmp; |
237 | - cyb = yTmp + ch; |
238 | - |
239 | - foreach (CompWindow *w, screen->windows ()) |
240 | - { |
241 | - if (!windowIsPlaceRelevant (w)) |
242 | - continue; |
243 | - |
244 | - xl = w->serverX () - w->border ().left; |
245 | - yt = w->serverY () - w->border ().top; |
246 | - xr = w->serverX () + w->serverWidth () + |
247 | - w->border ().right + |
248 | - w->serverGeometry ().border () * 2; |
249 | - yb = w->serverY () + w->serverHeight () + |
250 | - w->border ().bottom + |
251 | - w->serverGeometry ().border () * 2; |
252 | - |
253 | - /* if windows overlap, calc the overall overlapping */ |
254 | - if (cxl < xr && cxr > xl && cyt < yb && cyb > yt) |
255 | - { |
256 | - xl = MAX (cxl, xl); |
257 | - xr = MIN (cxr, xr); |
258 | - yt = MAX (cyt, yt); |
259 | - yb = MIN (cyb, yb); |
260 | - |
261 | - if (w->state () & CompWindowStateAboveMask) |
262 | - overlap += 16 * (xr - xl) * (yb - yt); |
263 | - else if (w->state () & CompWindowStateBelowMask) |
264 | - overlap += 0; |
265 | - else |
266 | - overlap += (xr - xl) * (yb - yt); |
267 | - } |
268 | - } |
269 | - } |
270 | - |
271 | - /* CT first time we get no overlap we stop */ |
272 | - if (overlap == NONE) |
273 | - { |
274 | - xOptimal = xTmp; |
275 | - yOptimal = yTmp; |
276 | - break; |
277 | - } |
278 | - |
279 | - if (firstPass) |
280 | - { |
281 | - firstPass = false; |
282 | - minOverlap = overlap; |
283 | - } |
284 | - /* CT save the best position and the minimum overlap up to now */ |
285 | - else if (overlap >= NONE && overlap < minOverlap) |
286 | - { |
287 | - minOverlap = overlap; |
288 | - xOptimal = xTmp; |
289 | - yOptimal = yTmp; |
290 | - } |
291 | - |
292 | - /* really need to loop? test if there's any overlap */ |
293 | - if (overlap > NONE) |
294 | - { |
295 | - possible = workArea.right (); |
296 | - |
297 | - if (possible - cw > xTmp) |
298 | - possible -= cw; |
299 | - |
300 | - /* compare to the position of each client on the same desk */ |
301 | - foreach (CompWindow *w, screen->windows ()) |
302 | - { |
303 | - if (!windowIsPlaceRelevant (w)) |
304 | - continue; |
305 | - |
306 | - xl = w->serverX () - w->border ().left; |
307 | - yt = w->serverY () - w->border ().top; |
308 | - xr = w->serverX () + w->serverWidth () + |
309 | - w->border ().right + |
310 | - w->serverGeometry ().border () * 2; |
311 | - yb = w->serverY () + w->serverHeight () + |
312 | - w->border ().bottom + |
313 | - w->serverGeometry ().border () * 2; |
314 | - |
315 | - /* if not enough room above or under the current |
316 | - * client determine the first non-overlapped x position |
317 | - */ |
318 | - if (yTmp < yb && yt < ch + yTmp) |
319 | - { |
320 | - if (xr > xTmp && possible > xr) |
321 | - possible = xr; |
322 | - |
323 | - basket = xl - cw; |
324 | - if (basket > xTmp && possible > basket) |
325 | - possible = basket; |
326 | - } |
327 | - } |
328 | - xTmp = possible; |
329 | - } |
330 | - /* else ==> not enough x dimension (overlap was wrong on horizontal) */ |
331 | - else if (overlap == W_WRONG) |
332 | - { |
333 | - xTmp = workArea.x (); |
334 | - possible = workArea.bottom (); |
335 | - |
336 | - if (possible - ch > yTmp) |
337 | - possible -= ch; |
338 | - |
339 | - /* test the position of each window on the desk */ |
340 | - foreach (CompWindow *w, screen->windows ()) |
341 | - { |
342 | - if (!windowIsPlaceRelevant (w)) |
343 | - continue; |
344 | - |
345 | - xl = w->serverX () - w->border ().left; |
346 | - yt = w->serverY () - w->border ().top; |
347 | - xr = w->serverX () + w->serverWidth () + |
348 | - w->border ().right + |
349 | - w->serverGeometry ().border () * 2; |
350 | - yb = w->serverY () + w->serverHeight () + |
351 | - w->border ().bottom + |
352 | - w->serverGeometry ().border () * 2; |
353 | - |
354 | - /* if not enough room to the left or right of the current |
355 | - * client determine the first non-overlapped y position |
356 | - */ |
357 | - if (yb > yTmp && possible > yb) |
358 | - possible = yb; |
359 | - |
360 | - basket = yt - ch; |
361 | - if (basket > yTmp && possible > basket) |
362 | - possible = basket; |
363 | - } |
364 | - yTmp = possible; |
365 | - } |
366 | - } |
367 | - while (overlap != NONE && overlap != H_WRONG && yTmp < workArea.bottom ()); |
368 | - |
369 | - if (ch >= workArea.height ()) |
370 | - yOptimal = workArea.y (); |
371 | - |
372 | - pos.setX (xOptimal + window->border ().left); |
373 | - pos.setY (yOptimal + window->border ().top); |
374 | + compiz::place::smart (this, pos, placeables); |
375 | } |
376 | |
377 | static void |
378 | @@ -945,32 +786,22 @@ |
379 | |
380 | static bool |
381 | rectOverlapsWindow (const CompRect &rect, |
382 | - const CompWindowList &windows) |
383 | + const compiz::place::Placeable::Vector &placeables) |
384 | { |
385 | CompRect dest; |
386 | |
387 | - foreach (CompWindow *other, windows) |
388 | + foreach (compiz::place::Placeable *other, placeables) |
389 | { |
390 | CompRect intersect; |
391 | + CompRect sbr = other->geometry (); |
392 | + sbr.setLeft (sbr.left () - other->extents ().left); |
393 | + sbr.setRight (sbr.right () + other->extents ().right); |
394 | + sbr.setTop (sbr.top () - other->extents ().top); |
395 | + sbr.setBottom (sbr.bottom () - other->extents ().bottom); |
396 | |
397 | - switch (other->type ()) { |
398 | - case CompWindowTypeDockMask: |
399 | - case CompWindowTypeSplashMask: |
400 | - case CompWindowTypeDesktopMask: |
401 | - case CompWindowTypeDialogMask: |
402 | - case CompWindowTypeModalDialogMask: |
403 | - case CompWindowTypeFullscreenMask: |
404 | - case CompWindowTypeUnknownMask: |
405 | - break; |
406 | - case CompWindowTypeNormalMask: |
407 | - case CompWindowTypeUtilMask: |
408 | - case CompWindowTypeToolbarMask: |
409 | - case CompWindowTypeMenuMask: |
410 | - intersect = rect & other->serverBorderRect (); |
411 | - if (!intersect.isEmpty ()) |
412 | - return true; |
413 | - break; |
414 | - } |
415 | + intersect = rect & sbr; |
416 | + if (!intersect.isEmpty ()) |
417 | + return true; |
418 | } |
419 | |
420 | return false; |
421 | @@ -985,7 +816,7 @@ |
422 | * don't want to create a 1x1 Emacs. |
423 | */ |
424 | bool |
425 | -PlaceWindow::cascadeFindFirstFit (const CompWindowList &windows, |
426 | +PlaceWindow::cascadeFindFirstFit (const Placeable::Vector &placeables, |
427 | const CompRect &workArea, |
428 | CompPoint &pos) |
429 | { |
430 | @@ -997,49 +828,59 @@ |
431 | * existing window in each of those cases. |
432 | */ |
433 | bool retval = false; |
434 | - CompWindowList belowSorted, rightSorted; |
435 | - CompRect rect; |
436 | + Placeable::Vector belowSorted, rightSorted; |
437 | |
438 | /* Below each window */ |
439 | - belowSorted = windows; |
440 | - belowSorted.sort (compareLeftmost); |
441 | - belowSorted.sort (compareTopmost); |
442 | + belowSorted = placeables; |
443 | + std::sort (belowSorted.begin (), belowSorted.end (), compareLeftmost); |
444 | + std::sort (belowSorted.begin (), belowSorted.end (), compareTopmost); |
445 | |
446 | /* To the right of each window */ |
447 | - rightSorted = windows; |
448 | - rightSorted.sort (compareTopmost); |
449 | - rightSorted.sort (compareLeftmost); |
450 | - |
451 | - rect = window->serverBorderRect (); |
452 | + rightSorted = placeables; |
453 | + std::sort (belowSorted.begin (), belowSorted.end (), compareTopmost); |
454 | + std::sort (belowSorted.begin (), belowSorted.end (), compareLeftmost); |
455 | + |
456 | + CompRect rect = this->geometry (); |
457 | + |
458 | + rect.setLeft (rect.left () - this->extents ().left); |
459 | + rect.setRight (rect.right () + this->extents ().right); |
460 | + rect.setTop (rect.top () - this->extents ().top); |
461 | + rect.setBottom (rect.bottom () - this->extents ().bottom); |
462 | + |
463 | centerTileRectInArea (rect, workArea); |
464 | |
465 | - if (workArea.contains (rect) && !rectOverlapsWindow (rect, windows)) |
466 | + if (workArea.contains (rect) && !rectOverlapsWindow (rect, placeables)) |
467 | { |
468 | - pos.setX (rect.x () + window->border ().left); |
469 | - pos.setY (rect.y () + window->border ().top); |
470 | + pos.setX (rect.x () + this->extents ().left); |
471 | + pos.setY (rect.y () + this->extents ().top); |
472 | retval = true; |
473 | } |
474 | |
475 | if (!retval) |
476 | { |
477 | /* try below each window */ |
478 | - foreach (CompWindow *w, belowSorted) |
479 | + foreach (Placeable *p, belowSorted) |
480 | { |
481 | CompRect outerRect; |
482 | |
483 | if (retval) |
484 | break; |
485 | |
486 | - outerRect = w->serverBorderRect (); |
487 | - |
488 | - rect.setX (outerRect.x ()); |
489 | - rect.setY (outerRect.bottom ()); |
490 | + outerRect = p->geometry (); |
491 | + |
492 | + outerRect.setLeft (rect.left () - this->extents ().left); |
493 | + outerRect.setRight (rect.right () + this->extents ().right); |
494 | + outerRect.setTop (rect.top () - this->extents ().top); |
495 | + outerRect.setBottom (rect.bottom () - this->extents ().bottom); |
496 | + |
497 | + outerRect.setX (outerRect.x ()); |
498 | + outerRect.setY (outerRect.bottom ()); |
499 | |
500 | if (workArea.contains (rect) && |
501 | !rectOverlapsWindow (rect, belowSorted)) |
502 | { |
503 | - pos.setX (rect.x () + window->border ().left); |
504 | - pos.setY (rect.y () + window->border ().top); |
505 | + pos.setX (rect.x () + this->extents ().left); |
506 | + pos.setY (rect.y () + this->extents ().top); |
507 | retval = true; |
508 | } |
509 | } |
510 | @@ -1048,23 +889,28 @@ |
511 | if (!retval) |
512 | { |
513 | /* try to the right of each window */ |
514 | - foreach (CompWindow *w, rightSorted) |
515 | + foreach (Placeable *p, rightSorted) |
516 | { |
517 | CompRect outerRect; |
518 | |
519 | if (retval) |
520 | break; |
521 | |
522 | - outerRect = w->serverBorderRect (); |
523 | - |
524 | - rect.setX (outerRect.right ()); |
525 | - rect.setY (outerRect.y ()); |
526 | + outerRect = p->geometry (); |
527 | + |
528 | + outerRect.setLeft (rect.left () - this->extents ().left); |
529 | + outerRect.setRight (rect.right () + this->extents ().right); |
530 | + outerRect.setTop (rect.top () - this->extents ().top); |
531 | + outerRect.setBottom (rect.bottom () - this->extents ().bottom); |
532 | + |
533 | + outerRect.setX (outerRect.right ()); |
534 | + outerRect.setY (outerRect.y ()); |
535 | |
536 | if (workArea.contains (rect) && |
537 | !rectOverlapsWindow (rect, rightSorted)) |
538 | { |
539 | - pos.setX (rect.x () + w->border ().left); |
540 | - pos.setY (rect.y () + w->border ().top); |
541 | + pos.setX (rect.x () + this->extents ().left); |
542 | + pos.setY (rect.y () + this->extents ().top); |
543 | retval = true; |
544 | } |
545 | } |
546 | @@ -1074,19 +920,19 @@ |
547 | } |
548 | |
549 | void |
550 | -PlaceWindow::cascadeFindNext (const CompWindowList &windows, |
551 | - const CompRect &workArea, |
552 | - CompPoint &pos) |
553 | +PlaceWindow::cascadeFindNext (const Placeable::Vector &placeables, |
554 | + const CompRect &workArea, |
555 | + CompPoint &pos) |
556 | { |
557 | - CompWindowList sorted; |
558 | - CompWindowList::iterator iter; |
559 | - int cascadeX, cascadeY; |
560 | - int xThreshold, yThreshold; |
561 | - int winWidth, winHeight; |
562 | - int cascadeStage; |
563 | + Placeable::Vector sorted; |
564 | + Placeable::Vector::iterator iter; |
565 | + int cascadeX, cascadeY; |
566 | + int xThreshold, yThreshold; |
567 | + int winWidth, winHeight; |
568 | + int cascadeStage; |
569 | |
570 | - sorted = windows; |
571 | - sorted.sort (compareNorthWestCorner); |
572 | + sorted = placeables; |
573 | + std::sort (sorted.begin (), sorted.end (), compareNorthWestCorner); |
574 | |
575 | /* This is a "fuzzy" cascade algorithm. |
576 | * For each window in the list, we find where we'd cascade a |
577 | @@ -1099,8 +945,8 @@ |
578 | */ |
579 | #define CASCADE_FUZZ 15 |
580 | |
581 | - xThreshold = MAX (window->border ().left, CASCADE_FUZZ); |
582 | - yThreshold = MAX (window->border ().top, CASCADE_FUZZ); |
583 | + xThreshold = MAX (this->extents ().left, CASCADE_FUZZ); |
584 | + yThreshold = MAX (this->extents ().top, CASCADE_FUZZ); |
585 | |
586 | /* Find furthest-SE origin of all workspaces. |
587 | * cascade_x, cascade_y are the target position |
588 | @@ -1118,12 +964,12 @@ |
589 | cascadeStage = 0; |
590 | for (iter = sorted.begin (); iter != sorted.end (); iter++) |
591 | { |
592 | - CompWindow *w = *iter; |
593 | + Placeable *p = *iter; |
594 | int wx, wy; |
595 | |
596 | /* we want frame position, not window position */ |
597 | - wx = w->serverX () - w->border ().left; |
598 | - wy = w->serverY () - w->border ().top; |
599 | + wx = p->geometry ().x () - p->extents ().left; |
600 | + wy = p->geometry ().y () - p->extents ().top; |
601 | |
602 | if (abs (wx - cascadeX) < xThreshold && |
603 | abs (wy - cascadeY) < yThreshold) |
604 | @@ -1132,8 +978,8 @@ |
605 | * point. The new window frame should go at the origin |
606 | * of the client window we're stacking above. |
607 | */ |
608 | - wx = cascadeX = w->serverX (); |
609 | - wy = cascadeY = w->serverY (); |
610 | + wx = cascadeX = p->geometry ().x (); |
611 | + wy = cascadeY = p->geometry ().y (); |
612 | |
613 | /* If we go off the screen, start over with a new cascade */ |
614 | if ((cascadeX + winWidth > workArea.right ()) || |
615 | @@ -1174,8 +1020,8 @@ |
616 | */ |
617 | |
618 | /* Convert coords to position of window, not position of frame. */ |
619 | - pos.setX (cascadeX + window->border ().left); |
620 | - pos.setY (cascadeY + window->border ().top); |
621 | + pos.setX (cascadeX + this->extents ().left); |
622 | + pos.setY (cascadeY + this->extents ().top); |
623 | } |
624 | |
625 | bool |
626 | |
627 | === modified file 'plugins/place/src/place.h' |
628 | --- plugins/place/src/place.h 2012-01-21 17:16:07 +0000 |
629 | +++ plugins/place/src/place.h 2012-01-30 18:23:23 +0000 |
630 | @@ -31,6 +31,7 @@ |
631 | |
632 | #include "place_options.h" |
633 | #include "screen-size-change.h" |
634 | +#include "smart.h" |
635 | |
636 | namespace compiz |
637 | { |
638 | @@ -39,7 +40,6 @@ |
639 | { |
640 | |
641 | CompWindowList collectStrutWindows (const CompWindowList &allWindows); |
642 | - |
643 | } |
644 | |
645 | } |
646 | @@ -74,6 +74,7 @@ |
647 | class PlaceWindow : |
648 | public PluginClassHandler<PlaceWindow, CompWindow>, |
649 | public compiz::place::ScreenSizeChangeObject, |
650 | + public compiz::place::Placeable, |
651 | public WindowInterface |
652 | { |
653 | public: |
654 | @@ -101,8 +102,11 @@ |
655 | const compiz::window::Geometry & getGeometry () const; |
656 | const CompPoint & getViewport () const; |
657 | const CompRect & getWorkarea (const compiz::window::Geometry &g) const; |
658 | + const CompRect & getWorkarea () const; |
659 | const compiz::window::extents::Extents & getExtents () const; |
660 | |
661 | + unsigned int getState () const; |
662 | + |
663 | private: |
664 | typedef enum { |
665 | NoPlacement = 0, |
666 | @@ -129,12 +133,12 @@ |
667 | void placeCentered (const CompRect& workArea, CompPoint& pos); |
668 | void placeRandom (const CompRect& workArea, CompPoint& pos); |
669 | void placePointer (const CompRect& workArea, CompPoint& pos); |
670 | - void placeSmart (const CompRect& workArea, CompPoint& pos); |
671 | + void placeSmart (CompPoint& pos, const compiz::place::Placeable::Vector &); |
672 | |
673 | - bool cascadeFindFirstFit (const CompWindowList& windows, |
674 | + bool cascadeFindFirstFit (const Placeable::Vector &placeabless, |
675 | const CompRect& workArea, |
676 | CompPoint &pos); |
677 | - void cascadeFindNext (const CompWindowList& windows, |
678 | + void cascadeFindNext (const Placeable::Vector &placeables, |
679 | const CompRect& workArea, |
680 | CompPoint &pos); |
681 | |
682 | |
683 | === added directory 'plugins/place/src/smart' |
684 | === added file 'plugins/place/src/smart/CMakeLists.txt' |
685 | --- plugins/place/src/smart/CMakeLists.txt 1970-01-01 00:00:00 +0000 |
686 | +++ plugins/place/src/smart/CMakeLists.txt 2012-01-30 18:23:23 +0000 |
687 | @@ -0,0 +1,62 @@ |
688 | +pkg_check_modules ( |
689 | + GLIBMM |
690 | + REQUIRED |
691 | + glibmm-2.4 glib-2.0 |
692 | +) |
693 | + |
694 | +INCLUDE_DIRECTORIES ( |
695 | + ${CMAKE_CURRENT_SOURCE_DIR}/include |
696 | + ${CMAKE_CURRENT_SOURCE_DIR}/src |
697 | + |
698 | + ${compiz_SOURCE_DIR}/src/point/include |
699 | + ${compiz_SOURCE_DIR}/src/rect/include |
700 | + ${compiz_SOURCE_DIR}/src/window/geometry/include |
701 | + ${compiz_SOURCE_DIR}/src/window/geometry-saver/include |
702 | + ${compiz_SOURCE_DIR}/src/window/extents/include |
703 | + ${compiz_SOURCE_DIR}/include |
704 | + |
705 | + ${Boost_INCLUDE_DIRS} |
706 | + |
707 | + ${GLIBMM_INCLUDE_DIRS} |
708 | +) |
709 | + |
710 | +LINK_DIRECTORIES (${GLIBMM_LIBRARY_DIRS}) |
711 | + |
712 | +SET ( |
713 | + PUBLIC_HEADERS |
714 | +) |
715 | + |
716 | +SET ( |
717 | + PRIVATE_HEADERS |
718 | + ${CMAKE_CURRENT_SOURCE_DIR}/include/smart.h |
719 | +) |
720 | + |
721 | +SET( |
722 | + SRCS |
723 | + ${CMAKE_CURRENT_SOURCE_DIR}/src/smart.cpp |
724 | +) |
725 | + |
726 | +ADD_LIBRARY( |
727 | + compiz_place_smart STATIC |
728 | + |
729 | + ${SRCS} |
730 | + |
731 | + ${PUBLIC_HEADERS} |
732 | + ${PRIVATE_HEADERS} |
733 | +) |
734 | + |
735 | +if (COMPIZ_BUILD_TESTING) |
736 | +ADD_SUBDIRECTORY( ${CMAKE_CURRENT_SOURCE_DIR}/tests ) |
737 | +endif (COMPIZ_BUILD_TESTING) |
738 | + |
739 | +SET_TARGET_PROPERTIES( |
740 | + compiz_place_smart PROPERTIES |
741 | + PUBLIC_HEADER "${PUBLIC_HEADERS}" |
742 | +) |
743 | + |
744 | +TARGET_LINK_LIBRARIES( |
745 | + compiz_place_smart |
746 | + |
747 | + compiz_core |
748 | + ${GLIBMM_LIBRARIES} |
749 | +) |
750 | |
751 | === added directory 'plugins/place/src/smart/include' |
752 | === added file 'plugins/place/src/smart/include/smart.h' |
753 | --- plugins/place/src/smart/include/smart.h 1970-01-01 00:00:00 +0000 |
754 | +++ plugins/place/src/smart/include/smart.h 2012-01-30 18:23:23 +0000 |
755 | @@ -0,0 +1,73 @@ |
756 | +/* |
757 | + * Copyright (C) 2001 Havoc Pennington |
758 | + * Copyright (C) 2002, 2003 Red Hat, Inc. |
759 | + * Copyright (C) 2003 Rob Adams |
760 | + * Copyright (C) 2005 Novell, Inc. |
761 | + * |
762 | + * This program is free software; you can redistribute it and/or |
763 | + * modify it under the terms of the GNU General Public License as |
764 | + * published by the Free Software Foundation; either version 2 of the |
765 | + * License, or (at your option) any later version. |
766 | + * |
767 | + * This program is distributed in the hope that it will be useful, but |
768 | + * WITHOUT ANY WARRANTY; without even the implied warranty of |
769 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
770 | + * General Public License for more details. |
771 | + * |
772 | + * You should have received a copy of the GNU General Public License |
773 | + * along with this program; if not, write to the Free Software |
774 | + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA |
775 | + * 02111-1307, USA. |
776 | + */ |
777 | + |
778 | +#ifndef _COMPIZ_PLACE_SMART_H |
779 | +#define _COMPIZ_PLACE_SMART_H |
780 | + |
781 | +#include <vector> |
782 | +#include <core/rect.h> |
783 | +#include <core/windowgeometry.h> |
784 | +#include <core/windowextents.h> |
785 | +#include <core/size.h> |
786 | +#include <core/point.h> |
787 | + |
788 | +namespace compiz |
789 | +{ |
790 | + namespace place |
791 | + { |
792 | + |
793 | + extern const unsigned int WindowAbove; |
794 | + extern const unsigned int WindowBelow; |
795 | + |
796 | + class Placeable |
797 | + { |
798 | + public: |
799 | + |
800 | + typedef std::vector <Placeable *> Vector; |
801 | + |
802 | + const compiz::window::Geometry & geometry () const { return getGeometry (); } |
803 | + const compiz::window::extents::Extents & extents () const { return getExtents (); } |
804 | + const CompRect & workArea () const { return getWorkarea (); } |
805 | + |
806 | + unsigned int state () const { return getState (); } |
807 | + |
808 | + virtual ~Placeable () = 0; |
809 | + |
810 | + protected: |
811 | + |
812 | + virtual const compiz::window::Geometry & getGeometry () const = 0; |
813 | + virtual const compiz::window::extents::Extents & getExtents () const = 0; |
814 | + virtual const CompRect & getWorkarea () const = 0; |
815 | + |
816 | + virtual unsigned int getState () const = 0; |
817 | + |
818 | + Placeable (); |
819 | + }; |
820 | + |
821 | + void smart (Placeable *placeable, |
822 | + CompPoint &pos, |
823 | + const compiz::place::Placeable::Vector &placeables); |
824 | + |
825 | + } |
826 | +} |
827 | + |
828 | +#endif |
829 | |
830 | === added directory 'plugins/place/src/smart/src' |
831 | === added file 'plugins/place/src/smart/src/smart.cpp' |
832 | --- plugins/place/src/smart/src/smart.cpp 1970-01-01 00:00:00 +0000 |
833 | +++ plugins/place/src/smart/src/smart.cpp 2012-01-30 18:23:23 +0000 |
834 | @@ -0,0 +1,199 @@ |
835 | +#include "smart.h" |
836 | +#include <boost/foreach.hpp> |
837 | + |
838 | +#ifndef foreach |
839 | +#define foreach BOOST_FOREACH |
840 | +#endif |
841 | + |
842 | +/* overlap types */ |
843 | +#define NONE 0 |
844 | +#define H_WRONG -1 |
845 | +#define W_WRONG -2 |
846 | + |
847 | +namespace compiz |
848 | +{ |
849 | + namespace place |
850 | + { |
851 | + const unsigned int WindowAbove = 1 << 0; |
852 | + const unsigned int WindowBelow = 1 << 1; |
853 | + |
854 | + Placeable::Placeable () |
855 | + { |
856 | + } |
857 | + |
858 | + Placeable::~Placeable () |
859 | + { |
860 | + } |
861 | + |
862 | + void smart (Placeable *placeable, |
863 | + CompPoint &pos, |
864 | + const compiz::place::Placeable::Vector &placeables) |
865 | + { |
866 | + /* |
867 | + * SmartPlacement by Cristian Tibirna (tibirna@kde.org) |
868 | + * adapted for kwm (16-19jan98) and for kwin (16Nov1999) using (with |
869 | + * permission) ideas from fvwm, authored by |
870 | + * Anthony Martin (amartin@engr.csulb.edu). |
871 | + * Xinerama supported added by Balaji Ramani (balaji@yablibli.com) |
872 | + * with ideas from xfce. |
873 | + * adapted for Compiz by Bellegarde Cedric (gnumdk(at)gmail.com) |
874 | + */ |
875 | + int overlap = 0, minOverlap = 0; |
876 | + |
877 | + /* temp holder */ |
878 | + int basket = 0; |
879 | + /* CT lame flag. Don't like it. What else would do? */ |
880 | + bool firstPass = true; |
881 | + |
882 | + /* get the maximum allowed windows space */ |
883 | + int xTmp = placeable->workArea ().x (); |
884 | + int yTmp = placeable->workArea ().y (); |
885 | + |
886 | + /* client gabarit */ |
887 | + int cw = placeable->geometry ().width () - 1; |
888 | + int ch = placeable->geometry ().height () - 1; |
889 | + |
890 | + int xOptimal = xTmp; |
891 | + int yOptimal = yTmp; |
892 | + |
893 | + /* loop over possible positions */ |
894 | + do |
895 | + { |
896 | + /* test if enough room in x and y directions */ |
897 | + if (yTmp + ch > placeable->workArea ().bottom () && ch < placeable->workArea ().height ()) |
898 | + overlap = H_WRONG; /* this throws the algorithm to an exit */ |
899 | + else if (xTmp + cw > placeable->workArea ().right ()) |
900 | + overlap = W_WRONG; |
901 | + else |
902 | + { |
903 | + overlap = NONE; /* initialize */ |
904 | + |
905 | + int cxl = xTmp; |
906 | + int cxr = xTmp + cw; |
907 | + int cyt = yTmp; |
908 | + int cyb = yTmp + ch; |
909 | + |
910 | + foreach (Placeable *p, placeables) |
911 | + { |
912 | + const compiz::window::Geometry &otherGeometry = p->geometry (); |
913 | + const compiz::window::extents::Extents &otherExtents = p->extents (); |
914 | + |
915 | + int xl = otherGeometry.x () - otherExtents.left; |
916 | + int yt = otherGeometry.y () - otherExtents.top; |
917 | + int xr = otherGeometry.x2 () + otherExtents.right + otherGeometry.border () * 2; |
918 | + int yb = otherGeometry.y2 () + otherExtents.bottom + otherGeometry.border () * 2; |
919 | + |
920 | + /* if windows overlap, calc the overall overlapping */ |
921 | + if (cxl < xr && cxr > xl && cyt < yb && cyb > yt) |
922 | + { |
923 | + xl = MAX (cxl, xl); |
924 | + xr = MIN (cxr, xr); |
925 | + yt = MAX (cyt, yt); |
926 | + yb = MIN (cyb, yb); |
927 | + |
928 | + if (p->state () & compiz::place::WindowAbove) |
929 | + overlap += 16 * (xr - xl) * (yb - yt); |
930 | + else if (p->state () & compiz::place::WindowBelow) |
931 | + overlap += 0; |
932 | + else |
933 | + overlap += (xr - xl) * (yb - yt); |
934 | + } |
935 | + } |
936 | + } |
937 | + |
938 | + /* CT first time we get no overlap we stop */ |
939 | + if (overlap == NONE) |
940 | + { |
941 | + xOptimal = xTmp; |
942 | + yOptimal = yTmp; |
943 | + break; |
944 | + } |
945 | + |
946 | + if (firstPass) |
947 | + { |
948 | + firstPass = false; |
949 | + minOverlap = overlap; |
950 | + } |
951 | + /* CT save the best position and the minimum overlap up to now */ |
952 | + else if (overlap >= NONE && overlap < minOverlap) |
953 | + { |
954 | + minOverlap = overlap; |
955 | + xOptimal = xTmp; |
956 | + yOptimal = yTmp; |
957 | + } |
958 | + |
959 | + /* really need to loop? test if there's any overlap */ |
960 | + if (overlap > NONE) |
961 | + { |
962 | + int possible = placeable->workArea ().right (); |
963 | + |
964 | + if (possible - cw > xTmp) |
965 | + possible -= cw; |
966 | + |
967 | + /* compare to the position of each client on the same desk */ |
968 | + foreach (Placeable *p, placeables) |
969 | + { |
970 | + const compiz::window::Geometry &otherGeometry = p->geometry (); |
971 | + const compiz::window::extents::Extents &otherExtents = p->extents (); |
972 | + |
973 | + int xl = otherGeometry.x () - otherExtents.left; |
974 | + int yt = otherGeometry.y () - otherExtents.top; |
975 | + int xr = otherGeometry.x2 () + otherExtents.right + otherGeometry.border () * 2; |
976 | + int yb = otherGeometry.y2 () + otherExtents.bottom + otherGeometry.border () * 2; |
977 | + |
978 | + /* if not enough room above or under the current |
979 | + * client determine the first non-overlapped x position |
980 | + */ |
981 | + if (yTmp < yb && yt < ch + yTmp) |
982 | + { |
983 | + if (xr > xTmp && possible > xr) |
984 | + possible = xr; |
985 | + |
986 | + basket = xl - cw; |
987 | + if (basket > xTmp && possible > basket) |
988 | + possible = basket; |
989 | + } |
990 | + } |
991 | + xTmp = possible; |
992 | + } |
993 | + /* else ==> not enough x dimension (overlap was wrong on horizontal) */ |
994 | + else if (overlap == W_WRONG) |
995 | + { |
996 | + xTmp = placeable->workArea ().x (); |
997 | + int possible = placeable->workArea ().bottom (); |
998 | + |
999 | + if (possible - ch > yTmp) |
1000 | + possible -= ch; |
1001 | + |
1002 | + /* test the position of each window on the desk */ |
1003 | + foreach (Placeable *p, placeables) |
1004 | + { |
1005 | + const compiz::window::Geometry &otherGeometry = p->geometry (); |
1006 | + const compiz::window::extents::Extents &otherExtents = p->extents (); |
1007 | + |
1008 | + int yt = otherGeometry.y () - otherExtents.top; |
1009 | + int yb = otherGeometry.y2 () + otherExtents.bottom + otherGeometry.border () * 2; |
1010 | + |
1011 | + /* if not enough room to the left or right of the current |
1012 | + * client determine the first non-overlapped y position |
1013 | + */ |
1014 | + if (yb > yTmp && possible > yb) |
1015 | + possible = yb; |
1016 | + |
1017 | + basket = yt - ch; |
1018 | + if (basket > yTmp && possible > basket) |
1019 | + possible = basket; |
1020 | + } |
1021 | + yTmp = possible; |
1022 | + } |
1023 | + } |
1024 | + while (overlap != NONE && overlap != H_WRONG && yTmp < placeable->workArea ().bottom ()); |
1025 | + |
1026 | + if (ch >= placeable->workArea ().height ()) |
1027 | + yOptimal = placeable->workArea ().y (); |
1028 | + |
1029 | + pos.setX (xOptimal + placeable->extents ().left); |
1030 | + pos.setY (yOptimal + placeable->extents ().top); |
1031 | + } |
1032 | + } |
1033 | +} |
1034 | |
1035 | === added directory 'plugins/place/src/smart/tests' |
1036 | === added file 'plugins/place/src/smart/tests/CMakeLists.txt' |
1037 | --- plugins/place/src/smart/tests/CMakeLists.txt 1970-01-01 00:00:00 +0000 |
1038 | +++ plugins/place/src/smart/tests/CMakeLists.txt 2012-01-30 18:23:23 +0000 |
1039 | @@ -0,0 +1,14 @@ |
1040 | +include_directories(${CMAKE_CURRENT_SOURCE_DIR}) |
1041 | + |
1042 | +add_executable (compiz_test_place_smart_on_screen |
1043 | + ${CMAKE_CURRENT_SOURCE_DIR}/offscreen/src/test-place-smart-on-screen.cpp) |
1044 | + |
1045 | +target_link_libraries (compiz_test_place_smart_on_screen |
1046 | + compiz_place_smart |
1047 | + ${GTEST_BOTH_LIBRARIES} |
1048 | + ${GMOCK_LIBRARY} |
1049 | + ${GMOCK_MAIN_LIBRARY} |
1050 | + ${CMAKE_THREAD_LIBS_INIT} # Link in pthread. |
1051 | + ) |
1052 | + |
1053 | +add_test (compiz_place_smart_on_screen compiz_test_place_smart_on_screen) |
1054 | |
1055 | === added directory 'plugins/place/src/smart/tests/offscreen' |
1056 | === added directory 'plugins/place/src/smart/tests/offscreen/src' |
1057 | === added file 'plugins/place/src/smart/tests/offscreen/src/test-place-smart-on-screen.cpp' |
1058 | --- plugins/place/src/smart/tests/offscreen/src/test-place-smart-on-screen.cpp 1970-01-01 00:00:00 +0000 |
1059 | +++ plugins/place/src/smart/tests/offscreen/src/test-place-smart-on-screen.cpp 2012-01-30 18:23:23 +0000 |
1060 | @@ -0,0 +1,156 @@ |
1061 | +/* |
1062 | + * Copyright © 2011 Canonical Ltd. |
1063 | + * |
1064 | + * Permission to use, copy, modify, distribute, and sell this software |
1065 | + * and its documentation for any purpose is hereby granted without |
1066 | + * fee, provided that the above copyright notice appear in all copies |
1067 | + * and that both that copyright notice and this permission notice |
1068 | + * appear in supporting documentation, and that the name of |
1069 | + * Canonical Ltd. not be used in advertising or publicity pertaining to |
1070 | + * distribution of the software without specific, written prior permission. |
1071 | + * Canonical Ltd. makes no representations about the suitability of this |
1072 | + * software for any purpose. It is provided "as is" without express or |
1073 | + * implied warranty. |
1074 | + * |
1075 | + * CANONICAL, LTD. DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, |
1076 | + * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN |
1077 | + * NO EVENT SHALL CANONICAL, LTD. BE LIABLE FOR ANY SPECIAL, INDIRECT OR |
1078 | + * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS |
1079 | + * OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, |
1080 | + * NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION |
1081 | + * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. |
1082 | + * |
1083 | + * Authored by: Sam Spilsbury <sam.spilsbury@canonical.com> |
1084 | + */ |
1085 | + |
1086 | +#include <gtest/gtest.h> |
1087 | +#include <gmock/gmock.h> |
1088 | +#include "smart.h" |
1089 | +#include <iostream> |
1090 | +#include <stdlib.h> |
1091 | +#include <cstring> |
1092 | + |
1093 | +#include <boost/foreach.hpp> |
1094 | + |
1095 | +#ifndef foreach |
1096 | +#define foreach BOOST_FOREACH |
1097 | +#endif |
1098 | + |
1099 | +class CompPlaceSmartOffscreenTest : |
1100 | + public ::testing::Test |
1101 | +{ |
1102 | +}; |
1103 | + |
1104 | +class MockPlaceableObject : |
1105 | + public compiz::place::Placeable |
1106 | +{ |
1107 | + public: |
1108 | + |
1109 | + MockPlaceableObject (const compiz::window::Geometry &geometry, |
1110 | + const compiz::window::extents::Extents &extents, |
1111 | + const std::vector <CompRect *> &availableWorkareas); |
1112 | + |
1113 | + const compiz::window::Geometry & getGeometry () const { return mGeometry; } |
1114 | + const CompRect & getWorkarea () const { return *mWorkarea; } |
1115 | + const compiz::window::extents::Extents & getExtents () const { return mExtents; } |
1116 | + unsigned int getState () const { return 0; } |
1117 | + |
1118 | + private: |
1119 | + |
1120 | + compiz::window::Geometry mGeometry; |
1121 | + CompRect *mWorkarea; |
1122 | + compiz::window::extents::Extents mExtents; |
1123 | +}; |
1124 | + |
1125 | +MockPlaceableObject::MockPlaceableObject (const compiz::window::Geometry &geometry, |
1126 | + const compiz::window::extents::Extents &extents, |
1127 | + const std::vector <CompRect *> &availableWorkareas) : |
1128 | + compiz::place::Placeable::Placeable (), |
1129 | + mGeometry (geometry), |
1130 | + mExtents (extents) |
1131 | +{ |
1132 | + unsigned int areaMax = 0; |
1133 | + CompRect *running = availableWorkareas.front (); |
1134 | + |
1135 | + /* Pick the workarea that we best intersect */ |
1136 | + foreach (CompRect *rect, availableWorkareas) |
1137 | + { |
1138 | + unsigned int area = abs ((*rect & static_cast <CompRect> (geometry)).area ()); |
1139 | + |
1140 | + if (area > areaMax) |
1141 | + { |
1142 | + running = rect; |
1143 | + areaMax = area; |
1144 | + } |
1145 | + } |
1146 | + |
1147 | + mWorkarea = running; |
1148 | +} |
1149 | + |
1150 | +TEST_F (CompPlaceSmartOffscreenTest, TestOffscreenOne) |
1151 | +{ |
1152 | + CompRect wa1 (0, 24, 1680, 1026); |
1153 | + CompRect wa2 (1680, 24, 1024, 744); |
1154 | + compiz::place::Placeable::Vector v; |
1155 | + |
1156 | + std::vector <CompRect *> workAreas; |
1157 | + workAreas.push_back (&wa1); |
1158 | + workAreas.push_back (&wa2); |
1159 | + |
1160 | + /* Intersects 1 */ |
1161 | + compiz::window::Geometry g (0, 0, 640, 480, 0); |
1162 | + compiz::window::extents::Extents e; |
1163 | + |
1164 | + e.left = 10; |
1165 | + e.right = 10; |
1166 | + e.top = 10; |
1167 | + e.bottom = 10; |
1168 | + |
1169 | + MockPlaceableObject p (g, e, workAreas); |
1170 | + |
1171 | + CompPoint pos (g.x (), g.y ()); |
1172 | + |
1173 | + compiz::place::smart (&p, pos, v); |
1174 | + |
1175 | + EXPECT_EQ (pos, CompPoint (10, 34)); |
1176 | + |
1177 | + /* Intersects 2 */ |
1178 | + |
1179 | + g = compiz::window::Geometry (1681, 0, 640, 480, 0); |
1180 | + |
1181 | + p = MockPlaceableObject (g, e, workAreas); |
1182 | + |
1183 | + compiz::place::smart (&p, pos, v); |
1184 | + |
1185 | + EXPECT_EQ (pos, CompPoint (1690, 34)); |
1186 | + |
1187 | + /* Intersects 2 partially */ |
1188 | + |
1189 | + g = compiz::window::Geometry (1681, 500, 640, 480, 0); |
1190 | + |
1191 | + p = MockPlaceableObject (g, e, workAreas); |
1192 | + |
1193 | + compiz::place::smart (&p, pos, v); |
1194 | + |
1195 | + EXPECT_EQ (pos, CompPoint (1690, 34)); |
1196 | + |
1197 | + /* Intersects 1 + 2 partially (1 more) */ |
1198 | + |
1199 | + g = compiz::window::Geometry (1300, 500, 640, 480, 0); |
1200 | + |
1201 | + p = MockPlaceableObject (g, e, workAreas); |
1202 | + |
1203 | + compiz::place::smart (&p, pos, v); |
1204 | + |
1205 | + EXPECT_EQ (pos, CompPoint (10, 34)); |
1206 | + |
1207 | + /* Intersects 1 + 2 partially (2 more) */ |
1208 | + |
1209 | + g = compiz::window::Geometry (1600, 500, 640, 480, 0); |
1210 | + |
1211 | + p = MockPlaceableObject (g, e, workAreas); |
1212 | + |
1213 | + compiz::place::smart (&p, pos, v); |
1214 | + |
1215 | + EXPECT_EQ (pos, CompPoint (1690, 34)); |
1216 | +} |
1217 | |
1218 | === added file 'plugins/place/src/smart/tests/offscreen/src/test-place-smart-onscren.cpp' |
1219 | --- plugins/place/src/smart/tests/offscreen/src/test-place-smart-onscren.cpp 1970-01-01 00:00:00 +0000 |
1220 | +++ plugins/place/src/smart/tests/offscreen/src/test-place-smart-onscren.cpp 2012-01-30 18:23:23 +0000 |
1221 | @@ -0,0 +1,107 @@ |
1222 | +/* |
1223 | + * Copyright © 2011 Canonical Ltd. |
1224 | + * |
1225 | + * Permission to use, copy, modify, distribute, and sell this software |
1226 | + * and its documentation for any purpose is hereby granted without |
1227 | + * fee, provided that the above copyright notice appear in all copies |
1228 | + * and that both that copyright notice and this permission notice |
1229 | + * appear in supporting documentation, and that the name of |
1230 | + * Canonical Ltd. not be used in advertising or publicity pertaining to |
1231 | + * distribution of the software without specific, written prior permission. |
1232 | + * Canonical Ltd. makes no representations about the suitability of this |
1233 | + * software for any purpose. It is provided "as is" without express or |
1234 | + * implied warranty. |
1235 | + * |
1236 | + * CANONICAL, LTD. DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, |
1237 | + * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN |
1238 | + * NO EVENT SHALL CANONICAL, LTD. BE LIABLE FOR ANY SPECIAL, INDIRECT OR |
1239 | + * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS |
1240 | + * OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, |
1241 | + * NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION |
1242 | + * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. |
1243 | + * |
1244 | + * Authored by: Sam Spilsbury <sam.spilsbury@canonical.com> |
1245 | + */ |
1246 | + |
1247 | +#include <gtest/gtest.h> |
1248 | +#include <gmock/gmock.h> |
1249 | +#include "smart.h" |
1250 | +#include <iostream> |
1251 | +#include <stdlib.h> |
1252 | +#include <cstring> |
1253 | + |
1254 | +class CompPlaceSmartOffscreenTest : |
1255 | + public ::testing::Test |
1256 | +{ |
1257 | +}; |
1258 | + |
1259 | +class MockPlaceableObject : |
1260 | + public compiz::place::Placeable |
1261 | +{ |
1262 | + public: |
1263 | + |
1264 | + MockPlaceableObject (const compiz::window::Geometry &geometry, |
1265 | + const compiz::window::extents::Extents &extents, |
1266 | + const std::vector <CompRect *> &availableWorkareas); |
1267 | + |
1268 | + const compiz::window::Geometry & getGeometry () const { return mGeometry; } |
1269 | + const CompRect & getWorkarea () const { return *mWorkarea; } |
1270 | + const compiz::window::extents::Extents & getExtents () const { return mExtents; } |
1271 | + |
1272 | + private: |
1273 | + |
1274 | + compiz::window::Geometry mGeometry; |
1275 | + CompRect *mWorkarea; |
1276 | + compiz::window::extents::Extents mExtents; |
1277 | +} |
1278 | + |
1279 | +MockPlaceableObject::MockPlaceableObject (const compiz::window::Geometry &geometry, |
1280 | + const compiz::window::extents::Extents &extents, |
1281 | + const std::vector <CompRect *> &availableWorkareas) : |
1282 | + compiz::place::Placeable::Placeable (), |
1283 | + mGeometry (geometry), |
1284 | + mExtents (extents) |
1285 | +{ |
1286 | + unsigned int areaMax = 0; |
1287 | + CompRect *running = availableWorkareas.front (); |
1288 | + |
1289 | + /* Pick the workarea that we best intersect */ |
1290 | + foreach (CompRect *rect, availableWorkareas) |
1291 | + { |
1292 | + unsigned int area = abs ((*rect & static_cast <CompRect &> (geometry)).area ()); |
1293 | + |
1294 | + if (area > areaMax) |
1295 | + { |
1296 | + running = rect; |
1297 | + areaMax = area; |
1298 | + } |
1299 | + } |
1300 | + |
1301 | + mWorkarea = running; |
1302 | +} |
1303 | + |
1304 | +TEST_F (CompPlaceSmartOffscreenTest, TestOffscreenOne) |
1305 | +{ |
1306 | + CompRect wa1 (0, 24, 1680, 1026); |
1307 | + CompRect wa2 (1680, 24, 1024, 744); |
1308 | + compiz::place::Placeable::Vector v; |
1309 | + |
1310 | + std::vector <CompRect *> workAreas; |
1311 | + workAreas.push_back (&wa1); |
1312 | + workAreas.push_back (&wa2); |
1313 | + |
1314 | + /* Intersects 1 */ |
1315 | + compiz::window::Geometry g (0, 0, 640, 480); |
1316 | + compiz::window::extents::Extents e (10, 10, 10, 10); |
1317 | + |
1318 | + MockPlaceableObject p (g, e, workAreas); |
1319 | + |
1320 | + CompPoint pos (g.x (), g.y ()); |
1321 | + |
1322 | + compiz::place::smart (p, pos, v); |
1323 | + |
1324 | + std::cout << pos.x () << pos.y () << std::endl; |
1325 | + |
1326 | + EXPECT_EQ (pos, CompPoint (0, 0)); |
1327 | +} |
1328 | + |
Whoops, missing a commit here