Merge lp:~3v1n0/unity/scale-close-middle-click into lp:unity
- scale-close-middle-click
- Merge into trunk
Proposed by
Marco Trevisan (Treviño)
Status: | Merged |
---|---|
Approved by: | Brandon Schaefer |
Approved revision: | no longer in the source branch. |
Merged at revision: | 2748 |
Proposed branch: | lp:~3v1n0/unity/scale-close-middle-click |
Merge into: | lp:unity |
Diff against target: |
1018 lines (+472/-175) 6 files modified
plugins/unityshell/src/ScreenIntrospection.h (+48/-0) plugins/unityshell/src/unityshell.cpp (+223/-156) plugins/unityshell/src/unityshell.h (+23/-19) tests/autopilot/unity/emulators/screen.py (+42/-0) tests/autopilot/unity/tests/__init__.py (+12/-0) tests/autopilot/unity/tests/test_spread.py (+124/-0) |
To merge this branch: | bzr merge lp:~3v1n0/unity/scale-close-middle-click |
Related bugs: |
|
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
Brandon Schaefer (community) | Approve | ||
Review via email: mp+126044@code.launchpad.net |
Commit message
UnityShell: enable closing on middle-click, fix scaled decoration sizes, fix theming issues, added scale autopilot tests
Description of the change
Improved the computation of an unity scaled window size, so that there won't be drawing issues, updated the corner radius value to match the system default, fix style issues on theme changed. Plus, lots of code cleanup and optimizations.
Added introspection for the UnityScreen and UnityWindows so that we can now use autopilot for them.
So, new AP tests for new scale features.
To post a comment you must log in.
Preview Diff
[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1 | === added file 'plugins/unityshell/src/ScreenIntrospection.h' | |||
2 | --- plugins/unityshell/src/ScreenIntrospection.h 1970-01-01 00:00:00 +0000 | |||
3 | +++ plugins/unityshell/src/ScreenIntrospection.h 2012-09-24 16:14:49 +0000 | |||
4 | @@ -0,0 +1,48 @@ | |||
5 | 1 | // -*- Mode: C++; indent-tabs-mode: nil; tab-width: 2 -*- | ||
6 | 2 | /* | ||
7 | 3 | * Copyright (C) 2012 Canonical Ltd | ||
8 | 4 | * | ||
9 | 5 | * This program is free software: you can redistribute it and/or modify | ||
10 | 6 | * it under the terms of the GNU General Public License version 3 as | ||
11 | 7 | * published by the Free Software Foundation. | ||
12 | 8 | * | ||
13 | 9 | * This program is distributed in the hope that it will be useful, | ||
14 | 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
15 | 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
16 | 12 | * GNU General Public License for more details. | ||
17 | 13 | * | ||
18 | 14 | * You should have received a copy of the GNU General Public License | ||
19 | 15 | * along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
20 | 16 | * | ||
21 | 17 | * Authored by: Marco Trevisan (Treviño) <marco.trevisan@canonical.com> | ||
22 | 18 | */ | ||
23 | 19 | |||
24 | 20 | #ifndef SCREEN_INTROSPECTION_H | ||
25 | 21 | #define SCREEN_INTROSPECTION_H | ||
26 | 22 | |||
27 | 23 | #include "Introspectable.h" | ||
28 | 24 | #include <core/core.h> | ||
29 | 25 | |||
30 | 26 | namespace unity | ||
31 | 27 | { | ||
32 | 28 | namespace debug | ||
33 | 29 | { | ||
34 | 30 | |||
35 | 31 | class ScreenIntrospection : public Introspectable | ||
36 | 32 | { | ||
37 | 33 | public: | ||
38 | 34 | ScreenIntrospection(CompScreen* screen); | ||
39 | 35 | |||
40 | 36 | protected: | ||
41 | 37 | std::string GetName() const; | ||
42 | 38 | void AddProperties(GVariantBuilder* builder); | ||
43 | 39 | IntrospectableList GetIntrospectableChildren(); | ||
44 | 40 | |||
45 | 41 | private: | ||
46 | 42 | CompScreen* screen_; | ||
47 | 43 | }; | ||
48 | 44 | |||
49 | 45 | } | ||
50 | 46 | } | ||
51 | 47 | |||
52 | 48 | #endif | ||
53 | 0 | 49 | ||
54 | === modified file 'plugins/unityshell/src/unityshell.cpp' | |||
55 | --- plugins/unityshell/src/unityshell.cpp 2012-09-21 21:52:27 +0000 | |||
56 | +++ plugins/unityshell/src/unityshell.cpp 2012-09-24 16:14:49 +0000 | |||
57 | @@ -26,6 +26,8 @@ | |||
58 | 26 | #include <Nux/WindowCompositor.h> | 26 | #include <Nux/WindowCompositor.h> |
59 | 27 | #include <Nux/NuxTimerTickSource.h> | 27 | #include <Nux/NuxTimerTickSource.h> |
60 | 28 | 28 | ||
61 | 29 | #include <UnityCore/Variant.h> | ||
62 | 30 | |||
63 | 29 | #include "BaseWindowRaiserImp.h" | 31 | #include "BaseWindowRaiserImp.h" |
64 | 30 | #include "IconRenderer.h" | 32 | #include "IconRenderer.h" |
65 | 31 | #include "Launcher.h" | 33 | #include "Launcher.h" |
66 | @@ -125,7 +127,6 @@ | |||
67 | 125 | , allowWindowPaint(false) | 127 | , allowWindowPaint(false) |
68 | 126 | , _key_nav_mode_requested(false) | 128 | , _key_nav_mode_requested(false) |
69 | 127 | , _last_output(nullptr) | 129 | , _last_output(nullptr) |
70 | 128 | , _bghash(NULL) | ||
71 | 129 | , grab_index_ (0) | 130 | , grab_index_ (0) |
72 | 130 | , painting_tray_ (false) | 131 | , painting_tray_ (false) |
73 | 131 | , last_scroll_event_(0) | 132 | , last_scroll_event_(0) |
74 | @@ -133,7 +134,7 @@ | |||
75 | 133 | , panel_texture_has_changed_(true) | 134 | , panel_texture_has_changed_(true) |
76 | 134 | , paint_panel_(false) | 135 | , paint_panel_(false) |
77 | 135 | , scale_just_activated_(false) | 136 | , scale_just_activated_(false) |
79 | 136 | , minimize_speed_controller(new WindowMinimizeSpeedController()) | 137 | , screen_introspection_(screen) |
80 | 137 | { | 138 | { |
81 | 138 | Timer timer; | 139 | Timer timer; |
82 | 139 | #ifndef USE_GLES | 140 | #ifndef USE_GLES |
83 | @@ -244,7 +245,7 @@ | |||
84 | 244 | // _bghash is a pointer. We don't want it to be created before Nux system has had a chance | 245 | // _bghash is a pointer. We don't want it to be created before Nux system has had a chance |
85 | 245 | // to start. BGHash relies on animations. Nux animation system starts after the WindowThread | 246 | // to start. BGHash relies on animations. Nux animation system starts after the WindowThread |
86 | 246 | // has been created. | 247 | // has been created. |
88 | 247 | _bghash = new BGHash(); | 248 | _bghash.reset(new BGHash()); |
89 | 248 | 249 | ||
90 | 249 | unity_a11y_init(wt.get()); | 250 | unity_a11y_init(wt.get()); |
91 | 250 | 251 | ||
92 | @@ -375,13 +376,15 @@ | |||
93 | 375 | Display* display = gdk_x11_display_get_xdisplay(gdk_display_get_default());; | 376 | Display* display = gdk_x11_display_get_xdisplay(gdk_display_get_default());; |
94 | 376 | XSelectInput(display, GDK_ROOT_WINDOW(), PropertyChangeMask); | 377 | XSelectInput(display, GDK_ROOT_WINDOW(), PropertyChangeMask); |
95 | 377 | LOG_INFO(logger) << "UnityScreen constructed: " << timer.ElapsedSeconds() << "s"; | 378 | LOG_INFO(logger) << "UnityScreen constructed: " << timer.ElapsedSeconds() << "s"; |
96 | 379 | |||
97 | 380 | panel::Style::Instance().changed.connect(sigc::mem_fun(this, &UnityScreen::OnPanelStyleChanged)); | ||
98 | 381 | |||
99 | 382 | minimize_speed_controller_.DurationChanged.connect( | ||
100 | 383 | sigc::mem_fun(this, &UnityScreen::OnMinimizeDurationChanged) | ||
101 | 384 | ); | ||
102 | 385 | |||
103 | 386 | AddChild(&screen_introspection_); | ||
104 | 378 | } | 387 | } |
105 | 379 | |||
106 | 380 | panel::Style::Instance().changed.connect(sigc::mem_fun(this, &UnityScreen::OnPanelStyleChanged)); | ||
107 | 381 | |||
108 | 382 | minimize_speed_controller->DurationChanged.connect( | ||
109 | 383 | sigc::mem_fun(this, &UnityScreen::OnMinimizeDurationChanged) | ||
110 | 384 | ); | ||
111 | 385 | } | 388 | } |
112 | 386 | 389 | ||
113 | 387 | UnityScreen::~UnityScreen() | 390 | UnityScreen::~UnityScreen() |
114 | @@ -391,7 +394,6 @@ | |||
115 | 391 | unity_a11y_finalize(); | 394 | unity_a11y_finalize(); |
116 | 392 | ::unity::ui::IconRenderer::DestroyTextures(); | 395 | ::unity::ui::IconRenderer::DestroyTextures(); |
117 | 393 | QuicklistManager::Destroy(); | 396 | QuicklistManager::Destroy(); |
118 | 394 | delete _bghash; | ||
119 | 395 | 397 | ||
120 | 396 | reset_glib_logging(); | 398 | reset_glib_logging(); |
121 | 397 | } | 399 | } |
122 | @@ -659,10 +661,15 @@ | |||
123 | 659 | wy = y + (last_bound.height - height) / 2; | 661 | wy = y + (last_bound.height - height) / 2; |
124 | 660 | } | 662 | } |
125 | 661 | 663 | ||
128 | 662 | void | 664 | void UnityScreen::OnPanelStyleChanged() |
127 | 663 | UnityScreen::OnPanelStyleChanged() | ||
129 | 664 | { | 665 | { |
130 | 665 | panel_texture_has_changed_ = true; | 666 | panel_texture_has_changed_ = true; |
131 | 667 | |||
132 | 668 | // Reload the windows themed textures | ||
133 | 669 | UnityWindow::CleanupSharedTextures(); | ||
134 | 670 | |||
135 | 671 | if (WindowManager::Default()->IsScaleActive()) | ||
136 | 672 | UnityWindow::SetupSharedTextures(); | ||
137 | 666 | } | 673 | } |
138 | 667 | 674 | ||
139 | 668 | void UnityScreen::paintDisplay() | 675 | void UnityScreen::paintDisplay() |
140 | @@ -1136,6 +1143,12 @@ | |||
141 | 1136 | DoAddDamage(); | 1143 | DoAddDamage(); |
142 | 1137 | handled = true; | 1144 | handled = true; |
143 | 1138 | } | 1145 | } |
144 | 1146 | else if (event->xbutton.button == Button2 && | ||
145 | 1147 | GetScaledGeometry().IsPointInside(event->xbutton.x_root, event->xbutton.y_root)) | ||
146 | 1148 | { | ||
147 | 1149 | middle_clicked_ = true; | ||
148 | 1150 | handled = true; | ||
149 | 1151 | } | ||
150 | 1139 | break; | 1152 | break; |
151 | 1140 | 1153 | ||
152 | 1141 | case ButtonRelease: | 1154 | case ButtonRelease: |
153 | @@ -1155,6 +1168,18 @@ | |||
154 | 1155 | 1168 | ||
155 | 1156 | handled = true; | 1169 | handled = true; |
156 | 1157 | } | 1170 | } |
157 | 1171 | |||
158 | 1172 | if (middle_clicked_) | ||
159 | 1173 | { | ||
160 | 1174 | if (event->xbutton.button == Button2 && | ||
161 | 1175 | GetScaledGeometry().IsPointInside(event->xbutton.x_root, event->xbutton.y_root)) | ||
162 | 1176 | { | ||
163 | 1177 | window->close(0); | ||
164 | 1178 | } | ||
165 | 1179 | |||
166 | 1180 | middle_clicked_ = false; | ||
167 | 1181 | handled = true; | ||
168 | 1182 | } | ||
169 | 1158 | } | 1183 | } |
170 | 1159 | break; | 1184 | break; |
171 | 1160 | 1185 | ||
172 | @@ -2277,8 +2302,7 @@ | |||
173 | 2277 | } | 2302 | } |
174 | 2278 | 2303 | ||
175 | 2279 | void UnityScreen::AddProperties(GVariantBuilder* builder) | 2304 | void UnityScreen::AddProperties(GVariantBuilder* builder) |
178 | 2280 | { | 2305 | {} |
177 | 2281 | } | ||
179 | 2282 | 2306 | ||
180 | 2283 | std::string UnityScreen::GetName() const | 2307 | std::string UnityScreen::GetName() const |
181 | 2284 | { | 2308 | { |
182 | @@ -2469,10 +2493,10 @@ | |||
183 | 2469 | CompOption::Value& value = o.value(); | 2493 | CompOption::Value& value = o.value(); |
184 | 2470 | CompOption::Value::Vector& list = value.list(); | 2494 | CompOption::Value::Vector& list = value.list(); |
185 | 2471 | CompOption::Value::Vector::iterator i = list.begin(); | 2495 | CompOption::Value::Vector::iterator i = list.begin(); |
190 | 2472 | if (i != list.end()) { | 2496 | if (i != list.end()) |
191 | 2473 | i->set(minimize_speed_controller->getDuration()); | 2497 | i->set(minimize_speed_controller_.getDuration()); |
192 | 2474 | } | 2498 | |
193 | 2475 | value.set(list); | 2499 | value.set(list); |
194 | 2476 | screen->setOptionForPlugin(p->vTable->name().c_str(), | 2500 | screen->setOptionForPlugin(p->vTable->name().c_str(), |
195 | 2477 | o.name().c_str(), value); | 2501 | o.name().c_str(), value); |
196 | 2478 | break; | 2502 | break; |
197 | @@ -2603,7 +2627,7 @@ | |||
198 | 2603 | case CompWindowNotifyMinimize: | 2627 | case CompWindowNotifyMinimize: |
199 | 2604 | /* Updating the count in dconf will trigger a "changed" signal to which | 2628 | /* Updating the count in dconf will trigger a "changed" signal to which |
200 | 2605 | * the method setting the new animation speed is attached */ | 2629 | * the method setting the new animation speed is attached */ |
202 | 2606 | UnityScreen::get(screen)->minimize_speed_controller->UpdateCount(); | 2630 | UnityScreen::get(screen)->minimize_speed_controller_.UpdateCount(); |
203 | 2607 | break; | 2631 | break; |
204 | 2608 | default: | 2632 | default: |
205 | 2609 | break; | 2633 | break; |
206 | @@ -3458,107 +3482,117 @@ | |||
207 | 3458 | WindowManager::Default()->terminate_spread.connect(sigc::mem_fun(this, &UnityWindow::OnTerminateSpreed)); | 3482 | WindowManager::Default()->terminate_spread.connect(sigc::mem_fun(this, &UnityWindow::OnTerminateSpreed)); |
208 | 3459 | } | 3483 | } |
209 | 3460 | 3484 | ||
219 | 3461 | void | 3485 | void UnityWindow::AddProperties(GVariantBuilder* builder) |
220 | 3462 | UnityWindow::DrawTexture(GLTexture* icon, | 3486 | { |
221 | 3463 | const GLWindowPaintAttrib& attrib, | 3487 | Window xid = window->id(); |
222 | 3464 | const GLMatrix& transform, | 3488 | auto const& swins = ScaleScreen::get(screen)->getWindows(); |
223 | 3465 | unsigned int mask, | 3489 | bool scaled = std::find(swins.begin(), swins.end(), ScaleWindow::get(window)) != swins.end(); |
224 | 3466 | float x, float y, | 3490 | auto wm = WindowManager::Default(); |
225 | 3467 | int &maxWidth, int &maxHeight) | 3491 | |
226 | 3468 | { | 3492 | variant::BuilderWrapper(builder) |
227 | 3469 | if (icon) | 3493 | .add(scaled ? GetScaledGeometry() : wm->GetWindowGeometry(xid)) |
228 | 3494 | .add("xid", xid) | ||
229 | 3495 | .add("title", wm->GetWindowName(xid)) | ||
230 | 3496 | .add("scaled", scaled) | ||
231 | 3497 | .add("scaled_close_x", close_button_geo_.x) | ||
232 | 3498 | .add("scaled_close_y", close_button_geo_.y) | ||
233 | 3499 | .add("scaled_close_width", close_button_geo_.width) | ||
234 | 3500 | .add("scaled_close_height", close_button_geo_.height); | ||
235 | 3501 | } | ||
236 | 3502 | |||
237 | 3503 | std::string UnityWindow::GetName() const | ||
238 | 3504 | { | ||
239 | 3505 | return "Window"; | ||
240 | 3506 | } | ||
241 | 3507 | |||
242 | 3508 | void UnityWindow::DrawTexture(GLTexture::List const& textures, GLWindowPaintAttrib const& attrib, | ||
243 | 3509 | GLMatrix const& transform, unsigned int mask, int x, int y) | ||
244 | 3510 | { | ||
245 | 3511 | for (auto const& texture : textures) | ||
246 | 3470 | { | 3512 | { |
261 | 3471 | int width, height; | 3513 | if (!texture) |
262 | 3472 | width = icon->width(); | 3514 | continue; |
263 | 3473 | height = icon->height(); | 3515 | |
250 | 3474 | |||
251 | 3475 | if (height > maxHeight) | ||
252 | 3476 | maxHeight = height; | ||
253 | 3477 | |||
254 | 3478 | if (width > maxWidth) | ||
255 | 3479 | maxWidth = width; | ||
256 | 3480 | |||
257 | 3481 | CompRegion iconReg(0, 0, width, height); | ||
258 | 3482 | GLTexture::MatrixList ml(1); | ||
259 | 3483 | |||
260 | 3484 | ml[0] = icon->matrix(); | ||
264 | 3485 | gWindow->vertexBuffer()->begin(); | 3516 | gWindow->vertexBuffer()->begin(); |
267 | 3486 | if (width && height) | 3517 | |
268 | 3487 | gWindow->glAddGeometry(ml, iconReg, iconReg); | 3518 | if (texture->width() && texture->height()) |
269 | 3519 | { | ||
270 | 3520 | GLTexture::MatrixList ml(1); | ||
271 | 3521 | ml[0] = texture->matrix(); | ||
272 | 3522 | CompRegion texture_region(0, 0, texture->width(), texture->height()); | ||
273 | 3523 | gWindow->glAddGeometry(ml, texture_region, texture_region); | ||
274 | 3524 | } | ||
275 | 3488 | 3525 | ||
276 | 3489 | if (gWindow->vertexBuffer()->end()) | 3526 | if (gWindow->vertexBuffer()->end()) |
277 | 3490 | { | 3527 | { |
278 | 3491 | GLMatrix wTransform(transform); | 3528 | GLMatrix wTransform(transform); |
279 | 3492 | |||
280 | 3493 | wTransform.translate(x, y, 0.0f); | 3529 | wTransform.translate(x, y, 0.0f); |
281 | 3494 | 3530 | ||
283 | 3495 | gWindow->glDrawTexture(icon, wTransform, attrib, mask); | 3531 | gWindow->glDrawTexture(texture, wTransform, attrib, mask); |
284 | 3496 | } | 3532 | } |
285 | 3497 | } | 3533 | } |
286 | 3498 | } | 3534 | } |
287 | 3499 | 3535 | ||
292 | 3500 | void | 3536 | void UnityWindow::RenderText(CairoContext const& context, int x, int y, int width, int height) |
289 | 3501 | UnityWindow::RenderText(UnityWindow::CairoContext const& context, | ||
290 | 3502 | float x, float y, | ||
291 | 3503 | float maxWidth, float maxHeight) | ||
293 | 3504 | { | 3537 | { |
294 | 3505 | panel::Style& style = panel::Style::Instance(); | 3538 | panel::Style& style = panel::Style::Instance(); |
296 | 3506 | std::string fontDescription(style.GetFontDescription(panel::PanelItem::TITLE)); | 3539 | std::string const& font_desc = style.GetFontDescription(panel::PanelItem::TITLE); |
297 | 3507 | 3540 | ||
298 | 3508 | glib::Object<PangoLayout> layout(pango_cairo_create_layout(context.cr_)); | 3541 | glib::Object<PangoLayout> layout(pango_cairo_create_layout(context.cr_)); |
300 | 3509 | std::shared_ptr<PangoFontDescription> font(pango_font_description_from_string(fontDescription.c_str()), | 3542 | std::shared_ptr<PangoFontDescription> font(pango_font_description_from_string(font_desc.c_str()), |
301 | 3510 | pango_font_description_free); | 3543 | pango_font_description_free); |
302 | 3511 | 3544 | ||
303 | 3512 | pango_layout_set_font_description(layout, font.get()); | 3545 | pango_layout_set_font_description(layout, font.get()); |
304 | 3513 | 3546 | ||
307 | 3514 | GdkScreen* gdkScreen = gdk_screen_get_default(); | 3547 | GdkScreen* gdk_screen = gdk_screen_get_default(); |
308 | 3515 | PangoContext* pCxt = pango_layout_get_context(layout); | 3548 | PangoContext* pango_ctx = pango_layout_get_context(layout); |
309 | 3516 | int dpi = style.GetTextDPI(); | 3549 | int dpi = style.GetTextDPI(); |
310 | 3517 | 3550 | ||
313 | 3518 | pango_cairo_context_set_font_options(pCxt, gdk_screen_get_font_options(gdkScreen)); | 3551 | pango_cairo_context_set_font_options(pango_ctx, gdk_screen_get_font_options(gdk_screen)); |
314 | 3519 | pango_cairo_context_set_resolution(pCxt, dpi / static_cast<float>(PANGO_SCALE)); | 3552 | pango_cairo_context_set_resolution(pango_ctx, dpi / static_cast<float>(PANGO_SCALE)); |
315 | 3520 | pango_layout_context_changed(layout); | 3553 | pango_layout_context_changed(layout); |
316 | 3521 | 3554 | ||
318 | 3522 | pango_layout_set_height(layout, maxHeight); | 3555 | std::string const& win_title = WindowManager::Default()->GetWindowName(window->id()); |
319 | 3556 | pango_layout_set_height(layout, height); | ||
320 | 3523 | pango_layout_set_width(layout, -1); //avoid wrap lines | 3557 | pango_layout_set_width(layout, -1); //avoid wrap lines |
321 | 3524 | pango_layout_set_auto_dir(layout, false); | 3558 | pango_layout_set_auto_dir(layout, false); |
325 | 3525 | pango_layout_set_text(layout, | 3559 | pango_layout_set_text(layout, win_title.c_str(), -1); |
323 | 3526 | WindowManager::Default()->GetWindowName(window->id()).c_str(), | ||
324 | 3527 | -1); | ||
326 | 3528 | 3560 | ||
327 | 3529 | /* update the size of the pango layout */ | 3561 | /* update the size of the pango layout */ |
328 | 3530 | pango_cairo_update_layout(context.cr_, layout); | 3562 | pango_cairo_update_layout(context.cr_, layout); |
335 | 3531 | cairo_set_operator(context.cr_, CAIRO_OPERATOR_OVER); | 3563 | |
336 | 3532 | cairo_set_source_rgba(context.cr_, | 3564 | GtkStyleContext* style_context = style.GetStyleContext(); |
337 | 3533 | 1.0, | 3565 | gtk_style_context_save(style_context); |
338 | 3534 | 1.0, | 3566 | |
339 | 3535 | 1.0, | 3567 | std::shared_ptr<GtkWidgetPath> widget_path(gtk_widget_path_new(), gtk_widget_path_free); |
340 | 3536 | 1.0); | 3568 | gtk_widget_path_append_type(widget_path.get(), GTK_TYPE_MENU_BAR); |
341 | 3569 | gtk_widget_path_append_type(widget_path.get(), GTK_TYPE_MENU_ITEM); | ||
342 | 3570 | gtk_widget_path_iter_set_name(widget_path.get(), -1 , "UnityPanelWidget"); | ||
343 | 3571 | |||
344 | 3572 | gtk_style_context_set_path(style_context, widget_path.get()); | ||
345 | 3573 | gtk_style_context_add_class(style_context, GTK_STYLE_CLASS_MENUBAR); | ||
346 | 3574 | gtk_style_context_add_class(style_context, GTK_STYLE_CLASS_MENUITEM); | ||
347 | 3537 | 3575 | ||
348 | 3538 | // alignment | 3576 | // alignment |
349 | 3539 | PangoRectangle lRect; | 3577 | PangoRectangle lRect; |
360 | 3540 | int textWidth, textHeight; | 3578 | pango_layout_get_extents(layout, nullptr, &lRect); |
361 | 3541 | 3579 | int text_width = lRect.width / PANGO_SCALE; | |
362 | 3542 | pango_layout_get_extents(layout, NULL, &lRect); | 3580 | int text_height = lRect.height / PANGO_SCALE; |
363 | 3543 | textWidth = lRect.width / PANGO_SCALE; | 3581 | y += (height - text_height) / 2.0f; |
364 | 3544 | textHeight = lRect.height / PANGO_SCALE; | 3582 | int text_space = width - x; |
365 | 3545 | 3583 | ||
366 | 3546 | y = ((maxHeight - textHeight) / 2.0) + y; | 3584 | if (text_width > text_space) |
357 | 3547 | cairo_translate(context.cr_, x, y); | ||
358 | 3548 | |||
359 | 3549 | if (textWidth > maxWidth) | ||
367 | 3550 | { | 3585 | { |
372 | 3551 | // apply a fade effect in the right corner | 3586 | // Cut the text with fade |
373 | 3552 | const int outPixels = textWidth - maxWidth; | 3587 | int out_pixels = text_width - text_space; |
374 | 3553 | const int fadingPixels = 35; | 3588 | const int fading_pixels = 35; |
375 | 3554 | const int fadingWidth = outPixels < fadingPixels ? outPixels : fadingPixels; | 3589 | int fading_width = (out_pixels < fading_pixels) ? out_pixels : fading_pixels; |
376 | 3555 | 3590 | ||
377 | 3556 | cairo_push_group(context.cr_); | 3591 | cairo_push_group(context.cr_); |
379 | 3557 | pango_cairo_show_layout(context.cr_, layout); | 3592 | gtk_render_layout(style_context, context.cr_, x, y, layout); |
380 | 3558 | cairo_pop_group_to_source(context.cr_); | 3593 | cairo_pop_group_to_source(context.cr_); |
381 | 3559 | 3594 | ||
384 | 3560 | std::shared_ptr<cairo_pattern_t> linpat(cairo_pattern_create_linear(maxWidth - fadingWidth, | 3595 | std::shared_ptr<cairo_pattern_t> linpat(cairo_pattern_create_linear(width - fading_width, y, width, y), |
383 | 3561 | y, maxWidth, y), | ||
385 | 3562 | cairo_pattern_destroy); | 3596 | cairo_pattern_destroy); |
386 | 3563 | cairo_pattern_add_color_stop_rgba(linpat.get(), 0, 0, 0, 0, 1); | 3597 | cairo_pattern_add_color_stop_rgba(linpat.get(), 0, 0, 0, 0, 1); |
387 | 3564 | cairo_pattern_add_color_stop_rgba(linpat.get(), 1, 0, 0, 0, 0); | 3598 | cairo_pattern_add_color_stop_rgba(linpat.get(), 1, 0, 0, 0, 0); |
388 | @@ -3566,61 +3600,55 @@ | |||
389 | 3566 | } | 3600 | } |
390 | 3567 | else | 3601 | else |
391 | 3568 | { | 3602 | { |
393 | 3569 | pango_cairo_show_layout(context.cr_, layout); | 3603 | gtk_render_layout(style_context, context.cr_, x, y, layout); |
394 | 3570 | } | 3604 | } |
395 | 3605 | |||
396 | 3606 | gtk_style_context_restore(style_context); | ||
397 | 3571 | } | 3607 | } |
398 | 3572 | 3608 | ||
405 | 3573 | void | 3609 | void UnityWindow::DrawWindowDecoration(GLWindowPaintAttrib const& attrib, |
406 | 3574 | UnityWindow::DrawWindowDecoration(GLWindowPaintAttrib const& attrib, | 3610 | GLMatrix const& transform, |
407 | 3575 | GLMatrix const& transform, | 3611 | unsigned int mask, |
408 | 3576 | unsigned int mask, | 3612 | bool highlighted, |
409 | 3577 | bool highlighted, | 3613 | int x, int y, unsigned width, unsigned height) |
404 | 3578 | int x, int y, unsigned width, unsigned height) | ||
410 | 3579 | { | 3614 | { |
411 | 3580 | // Paint a fake window decoration | 3615 | // Paint a fake window decoration |
412 | 3581 | CairoContext context(width, height); | 3616 | CairoContext context(width, height); |
413 | 3582 | 3617 | ||
414 | 3583 | cairo_save(context.cr_); | 3618 | cairo_save(context.cr_); |
415 | 3619 | |||
416 | 3620 | // Draw window decoration based on gtk style | ||
417 | 3584 | cairo_push_group(context.cr_); | 3621 | cairo_push_group(context.cr_); |
418 | 3622 | auto& style = panel::Style::Instance(); | ||
419 | 3623 | gtk_render_background(style.GetStyleContext(), context.cr_, 0, 0, width, height); | ||
420 | 3624 | gtk_render_frame(style.GetStyleContext(), context.cr_, 0, 0, width, height); | ||
421 | 3625 | cairo_pop_group_to_source(context.cr_); | ||
422 | 3585 | 3626 | ||
423 | 3586 | // Round window decoration top border | 3627 | // Round window decoration top border |
428 | 3587 | const double aspect = 1.0; | 3628 | const double aspect = ScaleWindow::get(window)->getCurrentPosition().scale; |
429 | 3588 | const double corner_radius = height / 10.0; | 3629 | const double radius = 8.0 * aspect; |
426 | 3589 | const double radius = corner_radius / aspect; | ||
427 | 3590 | const double degrees = M_PI / 180.0; | ||
430 | 3591 | 3630 | ||
431 | 3592 | cairo_new_sub_path(context.cr_); | 3631 | cairo_new_sub_path(context.cr_); |
435 | 3593 | 3632 | cairo_line_to(context.cr_, 0, height); | |
436 | 3594 | cairo_arc(context.cr_, radius, radius, radius, 180 * degrees, 270 * degrees); | 3633 | cairo_arc(context.cr_, radius, radius, radius, M_PI, -M_PI * 0.5f); |
437 | 3595 | cairo_arc(context.cr_, width - radius, radius, radius, -90 * degrees, 0 * degrees); | 3634 | cairo_line_to(context.cr_, width - radius, 0); |
438 | 3635 | cairo_arc(context.cr_, width - radius, radius, radius, M_PI * 0.5f, 0); | ||
439 | 3596 | cairo_line_to(context.cr_, width, height); | 3636 | cairo_line_to(context.cr_, width, height); |
440 | 3597 | cairo_line_to(context.cr_, 0, height); | ||
441 | 3598 | |||
442 | 3599 | cairo_close_path(context.cr_); | 3637 | cairo_close_path(context.cr_); |
453 | 3600 | cairo_clip(context.cr_); | 3638 | |
454 | 3601 | 3639 | cairo_fill(context.cr_); | |
455 | 3602 | // Draw window decoration based on gtk style | 3640 | |
446 | 3603 | auto& style = panel::Style::Instance(); | ||
447 | 3604 | gtk_render_background(style.GetStyleContext(), context.cr_, 0, 0, width, height); | ||
448 | 3605 | gtk_render_frame(style.GetStyleContext(), context.cr_, 0, 0, width, height); | ||
449 | 3606 | |||
450 | 3607 | cairo_pop_group_to_source(context.cr_); | ||
451 | 3608 | |||
452 | 3609 | cairo_paint_with_alpha(context.cr_, 1.0); | ||
456 | 3610 | cairo_restore(context.cr_); | 3641 | cairo_restore(context.cr_); |
457 | 3611 | 3642 | ||
458 | 3612 | if (highlighted) | 3643 | if (highlighted) |
459 | 3613 | { | 3644 | { |
460 | 3614 | // Draw windows title | 3645 | // Draw windows title |
461 | 3615 | const float xText = SCALE_ITEMS_PADDING * 2 + SCALE_CLOSE_ICON_SIZE; | 3646 | const float xText = SCALE_ITEMS_PADDING * 2 + SCALE_CLOSE_ICON_SIZE; |
463 | 3616 | RenderText(context, xText, 0.0, width - xText - SCALE_ITEMS_PADDING, height); | 3647 | RenderText(context, xText, 0.0, width - SCALE_ITEMS_PADDING, height); |
464 | 3617 | } | 3648 | } |
465 | 3618 | 3649 | ||
466 | 3619 | mask |= PAINT_WINDOW_BLEND_MASK; | 3650 | mask |= PAINT_WINDOW_BLEND_MASK; |
471 | 3620 | int maxWidth, maxHeight; | 3651 | DrawTexture(context.texture_, attrib, transform, mask, x, y); |
468 | 3621 | |||
469 | 3622 | for (GLTexture *icon : context.texture_) | ||
470 | 3623 | DrawTexture(icon, attrib, transform, mask, x, y, maxWidth , maxHeight); | ||
472 | 3624 | } | 3652 | } |
473 | 3625 | 3653 | ||
474 | 3626 | void UnityWindow::LoadCloseIcon(panel::WindowState state, GLTexture::List& texture) | 3654 | void UnityWindow::LoadCloseIcon(panel::WindowState state, GLTexture::List& texture) |
475 | @@ -3631,12 +3659,12 @@ | |||
476 | 3631 | auto& style = panel::Style::Instance(); | 3659 | auto& style = panel::Style::Instance(); |
477 | 3632 | auto const& files = style.GetWindowButtonFileNames(panel::WindowButtonType::CLOSE, state); | 3660 | auto const& files = style.GetWindowButtonFileNames(panel::WindowButtonType::CLOSE, state); |
478 | 3633 | 3661 | ||
480 | 3634 | CompString pName("unityshell"); | 3662 | CompString plugin("unityshell"); |
481 | 3635 | for (std::string const& file : files) | 3663 | for (std::string const& file : files) |
482 | 3636 | { | 3664 | { |
484 | 3637 | CompString fileName(file.c_str()); | 3665 | CompString file_name = file; |
485 | 3638 | CompSize size(SCALE_CLOSE_ICON_SIZE, SCALE_CLOSE_ICON_SIZE); | 3666 | CompSize size(SCALE_CLOSE_ICON_SIZE, SCALE_CLOSE_ICON_SIZE); |
487 | 3639 | texture = GLTexture::readImageToTexture(fileName, pName, size); | 3667 | texture = GLTexture::readImageToTexture(file_name, plugin, size); |
488 | 3640 | if (!texture.empty()) | 3668 | if (!texture.empty()) |
489 | 3641 | break; | 3669 | break; |
490 | 3642 | } | 3670 | } |
491 | @@ -3649,49 +3677,57 @@ | |||
492 | 3649 | else if (state == panel::WindowState::PRESSED) | 3677 | else if (state == panel::WindowState::PRESSED) |
493 | 3650 | suffix = "_pressed"; | 3678 | suffix = "_pressed"; |
494 | 3651 | 3679 | ||
496 | 3652 | CompString fileName((PKGDATADIR"/close_dash" + suffix + ".png").c_str()); | 3680 | CompString file_name(PKGDATADIR"/close_dash" + suffix + ".png"); |
497 | 3653 | CompSize size(SCALE_CLOSE_ICON_SIZE, SCALE_CLOSE_ICON_SIZE); | 3681 | CompSize size(SCALE_CLOSE_ICON_SIZE, SCALE_CLOSE_ICON_SIZE); |
499 | 3654 | texture = GLTexture::readImageToTexture(fileName, pName, size); | 3682 | texture = GLTexture::readImageToTexture(file_name, plugin, size); |
500 | 3655 | } | 3683 | } |
501 | 3656 | } | 3684 | } |
502 | 3657 | 3685 | ||
504 | 3658 | void UnityWindow::SetupScaleHeaderStyle() | 3686 | void UnityWindow::SetupSharedTextures() |
505 | 3659 | { | 3687 | { |
506 | 3660 | LoadCloseIcon(panel::WindowState::NORMAL, close_normal_tex_); | 3688 | LoadCloseIcon(panel::WindowState::NORMAL, close_normal_tex_); |
507 | 3661 | LoadCloseIcon(panel::WindowState::PRELIGHT, close_prelight_tex_); | 3689 | LoadCloseIcon(panel::WindowState::PRELIGHT, close_prelight_tex_); |
508 | 3662 | LoadCloseIcon(panel::WindowState::PRESSED, close_pressed_tex_); | 3690 | LoadCloseIcon(panel::WindowState::PRESSED, close_pressed_tex_); |
509 | 3663 | } | 3691 | } |
510 | 3664 | 3692 | ||
511 | 3693 | void UnityWindow::CleanupSharedTextures() | ||
512 | 3694 | { | ||
513 | 3695 | close_normal_tex_.clear(); | ||
514 | 3696 | close_prelight_tex_.clear(); | ||
515 | 3697 | close_pressed_tex_.clear(); | ||
516 | 3698 | } | ||
517 | 3699 | |||
518 | 3665 | void UnityWindow::scalePaintDecoration(GLWindowPaintAttrib const& attrib, | 3700 | void UnityWindow::scalePaintDecoration(GLWindowPaintAttrib const& attrib, |
519 | 3666 | GLMatrix const& transform, | 3701 | GLMatrix const& transform, |
520 | 3667 | CompRegion const& region, | 3702 | CompRegion const& region, |
521 | 3668 | unsigned int mask) | 3703 | unsigned int mask) |
522 | 3669 | { | 3704 | { |
523 | 3670 | ScaleWindow *scale_win = ScaleWindow::get(window); | 3705 | ScaleWindow *scale_win = ScaleWindow::get(window); |
524 | 3671 | if (!scale_win) | ||
525 | 3672 | return; | ||
526 | 3673 | |||
527 | 3674 | scale_win->scalePaintDecoration(attrib, transform, region, mask); | 3706 | scale_win->scalePaintDecoration(attrib, transform, region, mask); |
528 | 3675 | 3707 | ||
529 | 3676 | if (!scale_win->hasSlot()) // animation not finished | 3708 | if (!scale_win->hasSlot()) // animation not finished |
530 | 3677 | return; | 3709 | return; |
531 | 3678 | 3710 | ||
532 | 3679 | ScaleScreen* ss = ScaleScreen::get(screen); | 3711 | ScaleScreen* ss = ScaleScreen::get(screen); |
533 | 3712 | auto state = ss->getState(); | ||
534 | 3713 | |||
535 | 3714 | if (state != ScaleScreen::Wait && state != ScaleScreen::Out) | ||
536 | 3715 | return; | ||
537 | 3716 | |||
538 | 3717 | auto const& scaled_geo = GetScaledGeometry(); | ||
539 | 3718 | auto const& decoration_extents = window->border(); | ||
540 | 3719 | auto const& pos = scale_win->getCurrentPosition(); | ||
541 | 3720 | |||
542 | 3680 | const bool highlighted = (ss->getSelectedWindow() == window->id()); | 3721 | const bool highlighted = (ss->getSelectedWindow() == window->id()); |
557 | 3681 | 3722 | int width = scaled_geo.width; | |
558 | 3682 | ScalePosition const& pos = scale_win->getCurrentPosition(); | 3723 | int height = decoration_extents.top; |
559 | 3683 | auto const& border_rect = window->borderRect(); | 3724 | int x = scaled_geo.x; |
560 | 3684 | auto const& deco_ext = window->border(); | 3725 | int y = scaled_geo.y; |
561 | 3685 | 3726 | ||
562 | 3686 | const unsigned decoration_height = deco_ext.top; | 3727 | |
563 | 3687 | unsigned width = (border_rect.width() + deco_ext.left + deco_ext.right) * pos.scale; | 3728 | // If window is not highlighted, we draw the decoration at scaled size |
564 | 3688 | unsigned height = decoration_height * pos.scale; | 3729 | if (!highlighted) |
565 | 3689 | int x = pos.x() + border_rect.x(); | 3730 | height *= pos.scale; |
552 | 3690 | int y = pos.y() + border_rect.y() + decoration_height - height - 1; | ||
553 | 3691 | |||
554 | 3692 | // If window is highlighted, we draw the decoration at full size | ||
555 | 3693 | if (highlighted) | ||
556 | 3694 | height = decoration_height; | ||
566 | 3695 | 3731 | ||
567 | 3696 | DrawWindowDecoration(attrib, transform, mask, highlighted, x, y, width, height); | 3732 | DrawWindowDecoration(attrib, transform, mask, highlighted, x, y, width, height); |
568 | 3697 | 3733 | ||
569 | @@ -3699,30 +3735,25 @@ | |||
570 | 3699 | { | 3735 | { |
571 | 3700 | x += SCALE_ITEMS_PADDING; | 3736 | x += SCALE_ITEMS_PADDING; |
572 | 3701 | y += (height - SCALE_CLOSE_ICON_SIZE) / 2.0f; | 3737 | y += (height - SCALE_CLOSE_ICON_SIZE) / 2.0f; |
573 | 3702 | int max_height = 0; | ||
574 | 3703 | int max_width = 0; | ||
575 | 3704 | mask |= PAINT_WINDOW_BLEND_MASK; | 3738 | mask |= PAINT_WINDOW_BLEND_MASK; |
576 | 3705 | 3739 | ||
578 | 3706 | switch(close_icon_state_) | 3740 | switch (close_icon_state_) |
579 | 3707 | { | 3741 | { |
580 | 3708 | case panel::WindowState::NORMAL: | 3742 | case panel::WindowState::NORMAL: |
581 | 3709 | default: | 3743 | default: |
584 | 3710 | for (GLTexture *icon : close_normal_tex_) | 3744 | DrawTexture(close_normal_tex_, attrib, transform, mask, x, y); |
583 | 3711 | DrawTexture(icon, attrib, transform, mask, x, y, max_width , max_height); | ||
585 | 3712 | break; | 3745 | break; |
586 | 3713 | 3746 | ||
587 | 3714 | case panel::WindowState::PRELIGHT: | 3747 | case panel::WindowState::PRELIGHT: |
590 | 3715 | for (GLTexture *icon : close_prelight_tex_) | 3748 | DrawTexture(close_prelight_tex_, attrib, transform, mask, x, y); |
589 | 3716 | DrawTexture(icon, attrib, transform, mask, x, y, max_width , max_height); | ||
591 | 3717 | break; | 3749 | break; |
592 | 3718 | 3750 | ||
593 | 3719 | case panel::WindowState::PRESSED: | 3751 | case panel::WindowState::PRESSED: |
596 | 3720 | for (GLTexture *icon : close_pressed_tex_) | 3752 | DrawTexture(close_pressed_tex_, attrib, transform, mask, x, y); |
595 | 3721 | DrawTexture(icon, attrib, transform, mask, x, y, max_width , max_height); | ||
597 | 3722 | break; | 3753 | break; |
598 | 3723 | } | 3754 | } |
599 | 3724 | 3755 | ||
601 | 3725 | close_button_geo_.Set(x, y, max_height, max_width); | 3756 | close_button_geo_.Set(x, y, SCALE_CLOSE_ICON_SIZE, SCALE_CLOSE_ICON_SIZE); |
602 | 3726 | } | 3757 | } |
603 | 3727 | else if (!close_button_geo_.IsNull()) | 3758 | else if (!close_button_geo_.IsNull()) |
604 | 3728 | { | 3759 | { |
605 | @@ -3730,14 +3761,27 @@ | |||
606 | 3730 | } | 3761 | } |
607 | 3731 | } | 3762 | } |
608 | 3732 | 3763 | ||
609 | 3764 | nux::Geometry UnityWindow::GetScaledGeometry() | ||
610 | 3765 | { | ||
611 | 3766 | ScaleWindow *scale_win = ScaleWindow::get(window); | ||
612 | 3767 | |||
613 | 3768 | ScalePosition const& pos = scale_win->getCurrentPosition(); | ||
614 | 3769 | auto const& border_rect = window->borderRect(); | ||
615 | 3770 | auto const& deco_ext = window->border(); | ||
616 | 3771 | |||
617 | 3772 | const unsigned width = std::floor(border_rect.width() * pos.scale); | ||
618 | 3773 | const unsigned height = std::floor(border_rect.height() * pos.scale); | ||
619 | 3774 | const int x = pos.x() + window->x() - std::floor(deco_ext.left * pos.scale); | ||
620 | 3775 | const int y = pos.y() + window->y() - std::floor(deco_ext.top * pos.scale); | ||
621 | 3776 | |||
622 | 3777 | return nux::Geometry(x, y, width, height); | ||
623 | 3778 | } | ||
624 | 3779 | |||
625 | 3733 | void UnityWindow::OnInitiateSpreed() | 3780 | void UnityWindow::OnInitiateSpreed() |
626 | 3734 | { | 3781 | { |
627 | 3735 | auto const& windows = screen->windows(); | ||
628 | 3736 | if (std::find(windows.begin(), windows.end(), window) == windows.end()) | ||
629 | 3737 | return; | ||
630 | 3738 | |||
631 | 3739 | close_icon_state_ = panel::WindowState::NORMAL; | 3782 | close_icon_state_ = panel::WindowState::NORMAL; |
633 | 3740 | SetupScaleHeaderStyle(); | 3783 | middle_clicked_ = false; |
634 | 3784 | SetupSharedTextures(); | ||
635 | 3741 | 3785 | ||
636 | 3742 | WindowManager *wm = WindowManager::Default(); | 3786 | WindowManager *wm = WindowManager::Default(); |
637 | 3743 | Window xid = window->id(); | 3787 | Window xid = window->id(); |
638 | @@ -3748,10 +3792,6 @@ | |||
639 | 3748 | 3792 | ||
640 | 3749 | void UnityWindow::OnTerminateSpreed() | 3793 | void UnityWindow::OnTerminateSpreed() |
641 | 3750 | { | 3794 | { |
642 | 3751 | auto const& windows = screen->windows(); | ||
643 | 3752 | if (std::find(windows.begin(), windows.end(), window) == windows.end()) | ||
644 | 3753 | return; | ||
645 | 3754 | |||
646 | 3755 | WindowManager *wm = WindowManager::Default(); | 3795 | WindowManager *wm = WindowManager::Default(); |
647 | 3756 | Window xid = window->id(); | 3796 | Window xid = window->id(); |
648 | 3757 | 3797 | ||
649 | @@ -3813,6 +3853,33 @@ | |||
650 | 3813 | return true; | 3853 | return true; |
651 | 3814 | } | 3854 | } |
652 | 3815 | 3855 | ||
653 | 3856 | namespace debug | ||
654 | 3857 | { | ||
655 | 3858 | |||
656 | 3859 | ScreenIntrospection::ScreenIntrospection(CompScreen* screen) | ||
657 | 3860 | : screen_(screen) | ||
658 | 3861 | {} | ||
659 | 3862 | |||
660 | 3863 | std::string ScreenIntrospection::GetName() const | ||
661 | 3864 | { | ||
662 | 3865 | return "Screen"; | ||
663 | 3866 | } | ||
664 | 3867 | |||
665 | 3868 | void ScreenIntrospection::AddProperties(GVariantBuilder* builder) | ||
666 | 3869 | {} | ||
667 | 3870 | |||
668 | 3871 | Introspectable::IntrospectableList ScreenIntrospection::GetIntrospectableChildren() | ||
669 | 3872 | { | ||
670 | 3873 | IntrospectableList children; | ||
671 | 3874 | |||
672 | 3875 | for (auto const& win : screen_->windows()) | ||
673 | 3876 | children.push_back(UnityWindow::get(win)); | ||
674 | 3877 | |||
675 | 3878 | return children; | ||
676 | 3879 | } | ||
677 | 3880 | |||
678 | 3881 | } // debug namespace | ||
679 | 3882 | |||
680 | 3816 | namespace | 3883 | namespace |
681 | 3817 | { | 3884 | { |
682 | 3818 | 3885 | ||
683 | 3819 | 3886 | ||
684 | === modified file 'plugins/unityshell/src/unityshell.h' | |||
685 | --- plugins/unityshell/src/unityshell.h 2012-09-19 16:57:39 +0000 | |||
686 | +++ plugins/unityshell/src/unityshell.h 2012-09-24 16:14:49 +0000 | |||
687 | @@ -27,7 +27,6 @@ | |||
688 | 27 | #include <Nux/WindowThread.h> | 27 | #include <Nux/WindowThread.h> |
689 | 28 | #include <NuxCore/Property.h> | 28 | #include <NuxCore/Property.h> |
690 | 29 | #include <sigc++/sigc++.h> | 29 | #include <sigc++/sigc++.h> |
691 | 30 | #include <boost/shared_ptr.hpp> | ||
692 | 31 | 30 | ||
693 | 32 | #include <scale/scale.h> | 31 | #include <scale/scale.h> |
694 | 33 | #include <core/core.h> | 32 | #include <core/core.h> |
695 | @@ -50,6 +49,7 @@ | |||
696 | 50 | #include "PanelStyle.h" | 49 | #include "PanelStyle.h" |
697 | 51 | #include "UScreen.h" | 50 | #include "UScreen.h" |
698 | 52 | #include "DebugDBusInterface.h" | 51 | #include "DebugDBusInterface.h" |
699 | 52 | #include "ScreenIntrospection.h" | ||
700 | 53 | #include "SwitcherController.h" | 53 | #include "SwitcherController.h" |
701 | 54 | #include "UBusWrapper.h" | 54 | #include "UBusWrapper.h" |
702 | 55 | #include "UnityshellPrivate.h" | 55 | #include "UnityshellPrivate.h" |
703 | @@ -69,7 +69,7 @@ | |||
704 | 69 | 69 | ||
705 | 70 | /* base screen class */ | 70 | /* base screen class */ |
706 | 71 | class UnityScreen : | 71 | class UnityScreen : |
708 | 72 | public unity::debug::Introspectable, | 72 | public debug::Introspectable, |
709 | 73 | public sigc::trackable, | 73 | public sigc::trackable, |
710 | 74 | public ScreenInterface, | 74 | public ScreenInterface, |
711 | 75 | public CompositeScreenInterface, | 75 | public CompositeScreenInterface, |
712 | @@ -307,7 +307,7 @@ | |||
713 | 307 | 307 | ||
714 | 308 | nux::Property<nux::Geometry> primary_monitor_; | 308 | nux::Property<nux::Geometry> primary_monitor_; |
715 | 309 | 309 | ||
717 | 310 | BGHash* _bghash; | 310 | std::unique_ptr<BGHash> _bghash; |
718 | 311 | 311 | ||
719 | 312 | ::GLFramebufferObject *oldFbo; | 312 | ::GLFramebufferObject *oldFbo; |
720 | 313 | 313 | ||
721 | @@ -329,11 +329,13 @@ | |||
722 | 329 | nux::ObjectPtr<nux::IOpenGLBaseTexture> panel_texture_; | 329 | nux::ObjectPtr<nux::IOpenGLBaseTexture> panel_texture_; |
723 | 330 | 330 | ||
724 | 331 | bool scale_just_activated_; | 331 | bool scale_just_activated_; |
725 | 332 | WindowMinimizeSpeedController minimize_speed_controller_; | ||
726 | 333 | |||
727 | 334 | debug::ScreenIntrospection screen_introspection_; | ||
728 | 332 | 335 | ||
729 | 333 | UBusManager ubus_manager_; | 336 | UBusManager ubus_manager_; |
730 | 334 | glib::SourceManager sources_; | 337 | glib::SourceManager sources_; |
731 | 335 | 338 | ||
732 | 336 | WindowMinimizeSpeedController* minimize_speed_controller; | ||
733 | 337 | friend class UnityWindow; | 339 | friend class UnityWindow; |
734 | 338 | }; | 340 | }; |
735 | 339 | 341 | ||
736 | @@ -345,6 +347,7 @@ | |||
737 | 345 | public WrapableHandler<ScaleWindowInterface, 4>, | 347 | public WrapableHandler<ScaleWindowInterface, 4>, |
738 | 346 | public BaseSwitchWindow, | 348 | public BaseSwitchWindow, |
739 | 347 | public PluginClassHandler <UnityWindow, CompWindow>, | 349 | public PluginClassHandler <UnityWindow, CompWindow>, |
740 | 350 | public debug::Introspectable, | ||
741 | 348 | public sigc::trackable | 351 | public sigc::trackable |
742 | 349 | { | 352 | { |
743 | 350 | public: | 353 | public: |
744 | @@ -391,6 +394,7 @@ | |||
745 | 391 | 394 | ||
746 | 392 | bool place(CompPoint& pos); | 395 | bool place(CompPoint& pos); |
747 | 393 | CompPoint tryNotIntersectUI(CompPoint& pos); | 396 | CompPoint tryNotIntersectUI(CompPoint& pos); |
748 | 397 | nux::Geometry GetScaledGeometry(); | ||
749 | 394 | 398 | ||
750 | 395 | void paintThumbnail (nux::Geometry const& bounding, float alpha); | 399 | void paintThumbnail (nux::Geometry const& bounding, float alpha); |
751 | 396 | 400 | ||
752 | @@ -413,6 +417,10 @@ | |||
753 | 413 | const CompRegion &, | 417 | const CompRegion &, |
754 | 414 | unsigned int); | 418 | unsigned int); |
755 | 415 | 419 | ||
756 | 420 | protected: | ||
757 | 421 | std::string GetName() const; | ||
758 | 422 | void AddProperties(GVariantBuilder* builder); | ||
759 | 423 | |||
760 | 416 | private: | 424 | private: |
761 | 417 | struct CairoContext; | 425 | struct CairoContext; |
762 | 418 | 426 | ||
763 | @@ -449,23 +457,16 @@ | |||
764 | 449 | 457 | ||
765 | 450 | compiz::WindowInputRemoverLock::Ptr GetInputRemover (); | 458 | compiz::WindowInputRemoverLock::Ptr GetInputRemover (); |
766 | 451 | 459 | ||
771 | 452 | void DrawWindowDecoration(GLWindowPaintAttrib const& attrib, | 460 | void DrawWindowDecoration(GLWindowPaintAttrib const& attrib, GLMatrix const& transform, |
772 | 453 | GLMatrix const& transform, | 461 | unsigned int mask, bool highlighted, |
769 | 454 | unsigned int mask, | ||
770 | 455 | bool highlighted, | ||
773 | 456 | int x, int y, unsigned width, unsigned height); | 462 | int x, int y, unsigned width, unsigned height); |
783 | 457 | void DrawTexture(GLTexture *icon, | 463 | void DrawTexture(GLTexture::List const& textures, GLWindowPaintAttrib const& attrib, |
784 | 458 | const GLWindowPaintAttrib& attrib, | 464 | GLMatrix const& transform, unsigned int mask, int x, int y); |
785 | 459 | const GLMatrix& transform, | 465 | void RenderText(CairoContext const& context, int x, int y, int width, int height); |
777 | 460 | unsigned int mask, | ||
778 | 461 | float x, float y, | ||
779 | 462 | int &maxWidth, int &maxHeight); | ||
780 | 463 | void RenderText(CairoContext const& context, | ||
781 | 464 | float x, float y, | ||
782 | 465 | float maxWidth, float maxHeight); | ||
786 | 466 | 466 | ||
789 | 467 | void SetupScaleHeaderStyle(); | 467 | static void SetupSharedTextures(); |
790 | 468 | void LoadCloseIcon(panel::WindowState state, GLTexture::List& texture); | 468 | static void CleanupSharedTextures(); |
791 | 469 | static void LoadCloseIcon(panel::WindowState state, GLTexture::List& texture); | ||
792 | 469 | 470 | ||
793 | 470 | static GLTexture::List close_normal_tex_; | 471 | static GLTexture::List close_normal_tex_; |
794 | 471 | static GLTexture::List close_prelight_tex_; | 472 | static GLTexture::List close_prelight_tex_; |
795 | @@ -473,7 +474,10 @@ | |||
796 | 473 | compiz::WindowInputRemoverLock::Weak input_remover_; | 474 | compiz::WindowInputRemoverLock::Weak input_remover_; |
797 | 474 | panel::WindowState close_icon_state_; | 475 | panel::WindowState close_icon_state_; |
798 | 475 | nux::Geometry close_button_geo_; | 476 | nux::Geometry close_button_geo_; |
799 | 477 | bool middle_clicked_; | ||
800 | 476 | glib::Source::UniquePtr focus_desktop_timeout_; | 478 | glib::Source::UniquePtr focus_desktop_timeout_; |
801 | 479 | |||
802 | 480 | friend class UnityScreen; | ||
803 | 477 | }; | 481 | }; |
804 | 478 | 482 | ||
805 | 479 | 483 | ||
806 | 480 | 484 | ||
807 | === added file 'tests/autopilot/unity/emulators/screen.py' | |||
808 | --- tests/autopilot/unity/emulators/screen.py 1970-01-01 00:00:00 +0000 | |||
809 | +++ tests/autopilot/unity/emulators/screen.py 2012-09-24 16:14:49 +0000 | |||
810 | @@ -0,0 +1,42 @@ | |||
811 | 1 | # -*- Mode: Python; coding: utf-8; indent-tabs-mode: nil; tab-width: 4 -*- | ||
812 | 2 | # Copyright 2012 Canonical | ||
813 | 3 | # Author: Marco Trevisan (Treviño) | ||
814 | 4 | # | ||
815 | 5 | # This program is free software: you can redistribute it and/or modify it | ||
816 | 6 | # under the terms of the GNU General Public License version 3, as published | ||
817 | 7 | # by the Free Software Foundation. | ||
818 | 8 | # | ||
819 | 9 | |||
820 | 10 | from __future__ import absolute_import | ||
821 | 11 | |||
822 | 12 | import logging | ||
823 | 13 | from unity.emulators import UnityIntrospectionObject | ||
824 | 14 | logger = logging.getLogger(__name__) | ||
825 | 15 | |||
826 | 16 | |||
827 | 17 | class Screen(UnityIntrospectionObject): | ||
828 | 18 | """The Screen class.""" | ||
829 | 19 | |||
830 | 20 | @property | ||
831 | 21 | def windows(self): | ||
832 | 22 | """Return the available windows, or None.""" | ||
833 | 23 | return self.get_children_by_type(Window) | ||
834 | 24 | |||
835 | 25 | @property | ||
836 | 26 | def scaled_windows(self): | ||
837 | 27 | """Return the available scaled windows, or None.""" | ||
838 | 28 | return self.get_children_by_type(Window, scaled=True) | ||
839 | 29 | |||
840 | 30 | |||
841 | 31 | class Window(UnityIntrospectionObject): | ||
842 | 32 | """An individual window.""" | ||
843 | 33 | |||
844 | 34 | @property | ||
845 | 35 | def geometry(self): | ||
846 | 36 | """Returns a tuple of (x,y,w,h) for the current window.""" | ||
847 | 37 | return (self.x, self.y, self.width, self.height) | ||
848 | 38 | |||
849 | 39 | @property | ||
850 | 40 | def scale_close_geometry(self): | ||
851 | 41 | """Returns a tuple of (x,y,w,h) for the scale close button.""" | ||
852 | 42 | return (self.scaled_close_x, self.scaled_close_y, self.scaled_close_width, self.scaled_close_height) | ||
853 | 0 | 43 | ||
854 | === modified file 'tests/autopilot/unity/tests/__init__.py' | |||
855 | --- tests/autopilot/unity/tests/__init__.py 2012-07-12 20:54:59 +0000 | |||
856 | +++ tests/autopilot/unity/tests/__init__.py 2012-09-24 16:14:49 +0000 | |||
857 | @@ -20,6 +20,7 @@ | |||
858 | 20 | from testtools.content import text_content | 20 | from testtools.content import text_content |
859 | 21 | from testtools.matchers import Equals | 21 | from testtools.matchers import Equals |
860 | 22 | 22 | ||
861 | 23 | from unity.emulators.screen import Screen | ||
862 | 23 | from unity.emulators.dash import Dash | 24 | from unity.emulators.dash import Dash |
863 | 24 | from unity.emulators.hud import Hud | 25 | from unity.emulators.hud import Hud |
864 | 25 | from unity.emulators.launcher import LauncherController | 26 | from unity.emulators.launcher import LauncherController |
865 | @@ -114,6 +115,12 @@ | |||
866 | 114 | return True | 115 | return True |
867 | 115 | 116 | ||
868 | 116 | @property | 117 | @property |
869 | 118 | def screen(self): | ||
870 | 119 | if not getattr(self, '__screen', None): | ||
871 | 120 | self.__screen = self._get_screen() | ||
872 | 121 | return self.__screen | ||
873 | 122 | |||
874 | 123 | @property | ||
875 | 117 | def dash(self): | 124 | def dash(self): |
876 | 118 | if not getattr(self, '__dash', None): | 125 | if not getattr(self, '__dash', None): |
877 | 119 | self.__dash = Dash() | 126 | self.__dash = Dash() |
878 | @@ -155,6 +162,11 @@ | |||
879 | 155 | self.__workspace = WorkspaceManager() | 162 | self.__workspace = WorkspaceManager() |
880 | 156 | return self.__workspace | 163 | return self.__workspace |
881 | 157 | 164 | ||
882 | 165 | def _get_screen(self): | ||
883 | 166 | screens = Screen.get_all_instances() | ||
884 | 167 | self.assertThat(len(screens), Equals(1)) | ||
885 | 168 | return screens[0] | ||
886 | 169 | |||
887 | 158 | def _get_launcher_controller(self): | 170 | def _get_launcher_controller(self): |
888 | 159 | controllers = LauncherController.get_all_instances() | 171 | controllers = LauncherController.get_all_instances() |
889 | 160 | self.assertThat(len(controllers), Equals(1)) | 172 | self.assertThat(len(controllers), Equals(1)) |
890 | 161 | 173 | ||
891 | === added file 'tests/autopilot/unity/tests/test_spread.py' | |||
892 | --- tests/autopilot/unity/tests/test_spread.py 1970-01-01 00:00:00 +0000 | |||
893 | +++ tests/autopilot/unity/tests/test_spread.py 2012-09-24 16:14:49 +0000 | |||
894 | @@ -0,0 +1,124 @@ | |||
895 | 1 | # -*- Mode: Python; coding: utf-8; indent-tabs-mode: nil; tab-width: 4 -*- | ||
896 | 2 | # Copyright 2012 Canonical | ||
897 | 3 | # Author: Marco Trevisan (Treviño) | ||
898 | 4 | # | ||
899 | 5 | # This program is free software: you can redistribute it and/or modify it | ||
900 | 6 | # under the terms of the GNU General Public License version 3, as published | ||
901 | 7 | # by the Free Software Foundation. | ||
902 | 8 | |||
903 | 9 | from __future__ import absolute_import | ||
904 | 10 | |||
905 | 11 | from autopilot.matchers import Eventually | ||
906 | 12 | import logging | ||
907 | 13 | from time import sleep | ||
908 | 14 | from testtools.matchers import Equals, NotEquals | ||
909 | 15 | |||
910 | 16 | from unity.tests import UnityTestCase | ||
911 | 17 | from unity.emulators.screen import Screen | ||
912 | 18 | |||
913 | 19 | |||
914 | 20 | class SpreadTests(UnityTestCase): | ||
915 | 21 | """Spread tests""" | ||
916 | 22 | |||
917 | 23 | def start_test_application_windows(self, app_name, num_windows=2): | ||
918 | 24 | """Start a given number of windows of the requested application""" | ||
919 | 25 | self.close_all_app(app_name) | ||
920 | 26 | windows = [] | ||
921 | 27 | |||
922 | 28 | for i in range(num_windows): | ||
923 | 29 | win = self.start_app_window(app_name) | ||
924 | 30 | if len(windows): | ||
925 | 31 | self.assertThat(win.application, Equals(windows[-1].application)) | ||
926 | 32 | |||
927 | 33 | windows.append(win) | ||
928 | 34 | |||
929 | 35 | self.assertThat(len(windows), Equals(num_windows)) | ||
930 | 36 | |||
931 | 37 | return windows | ||
932 | 38 | |||
933 | 39 | def initiate_spread_for_screen(self): | ||
934 | 40 | """Initiate the Spread for all windows""" | ||
935 | 41 | self.addCleanup(self.keybinding, "spread/cancel") | ||
936 | 42 | self.keybinding("spread/start") | ||
937 | 43 | sleep(1) | ||
938 | 44 | self.assertThat(self.window_manager.scale_active, Eventually(Equals(True))) | ||
939 | 45 | |||
940 | 46 | |||
941 | 47 | def initiate_spread_for_application(self, desktop_id): | ||
942 | 48 | """Initiate the Spread for windows of the given app""" | ||
943 | 49 | icon = self.launcher.model.get_icon(desktop_id=desktop_id) | ||
944 | 50 | self.assertThat(lambda: icon, Eventually(NotEquals(None))) | ||
945 | 51 | launcher = self.launcher.get_launcher_for_monitor(self.screen_geo.get_primary_monitor()) | ||
946 | 52 | |||
947 | 53 | self.addCleanup(self.keybinding, "spread/cancel") | ||
948 | 54 | launcher.click_launcher_icon(icon) | ||
949 | 55 | self.assertThat(self.window_manager.scale_active_for_group, Eventually(Equals(True))) | ||
950 | 56 | |||
951 | 57 | def assertWindowIsNotScaled(self, xid): | ||
952 | 58 | """Assert that a window is not scaled""" | ||
953 | 59 | refresh_fn = lambda: xid in [w.xid for w in self.screen.scaled_windows] | ||
954 | 60 | self.assertThat(refresh_fn, Eventually(Equals(False))) | ||
955 | 61 | |||
956 | 62 | def assertWindowIsClosed(self, xid): | ||
957 | 63 | """Assert that a window is not in the list of the open windows""" | ||
958 | 64 | refresh_fn = lambda: xid in [w.x_id for w in self.bamf.get_open_windows()] | ||
959 | 65 | self.assertThat(refresh_fn, Eventually(Equals(False))) | ||
960 | 66 | |||
961 | 67 | |||
962 | 68 | def test_scale_application_windows(self): | ||
963 | 69 | """Test if all the windows of an application are scaled when application spread is initiated""" | ||
964 | 70 | [win1, win2] = self.start_test_application_windows("Calculator") | ||
965 | 71 | self.initiate_spread_for_application(win1.application.desktop_file) | ||
966 | 72 | |||
967 | 73 | self.assertThat(lambda: len(self.screen.scaled_windows), Eventually(Equals(2))) | ||
968 | 74 | self.assertThat(lambda: (win1.x_id and win2.x_id) in [w.xid for w in self.screen.scaled_windows], | ||
969 | 75 | Eventually(Equals(True))) | ||
970 | 76 | |||
971 | 77 | def test_scaled_window_is_focused_on_click(self): | ||
972 | 78 | """Test that a window is focused when clicked in spread""" | ||
973 | 79 | windows = self.start_test_application_windows("Calculator", 3) | ||
974 | 80 | self.initiate_spread_for_application(windows[0].application.desktop_file) | ||
975 | 81 | |||
976 | 82 | not_focused = [w for w in windows if not w.is_focused][0] | ||
977 | 83 | |||
978 | 84 | target_xid = not_focused.x_id | ||
979 | 85 | [target_win] = [w for w in self.screen.scaled_windows if w.xid == target_xid] | ||
980 | 86 | |||
981 | 87 | (x, y, w, h) = target_win.geometry | ||
982 | 88 | self.mouse.move(x + w / 2, y + h / 2) | ||
983 | 89 | sleep(.5) | ||
984 | 90 | self.mouse.click() | ||
985 | 91 | |||
986 | 92 | self.assertThat(lambda: not_focused.is_focused, Eventually(Equals(True))) | ||
987 | 93 | |||
988 | 94 | def test_scaled_window_closes_on_middle_click(self): | ||
989 | 95 | """Test that a window is closed when middle-clicked in spread""" | ||
990 | 96 | win = self.start_test_application_windows("Calculator", 2)[0] | ||
991 | 97 | self.initiate_spread_for_application(win.application.desktop_file) | ||
992 | 98 | |||
993 | 99 | target_xid = win.x_id | ||
994 | 100 | [target_win] = [w for w in self.screen.scaled_windows if w.xid == target_xid] | ||
995 | 101 | |||
996 | 102 | (x, y, w, h) = target_win.geometry | ||
997 | 103 | self.mouse.move(x + w / 2, y + h / 2) | ||
998 | 104 | sleep(.5) | ||
999 | 105 | self.mouse.click(button=2) | ||
1000 | 106 | |||
1001 | 107 | self.assertWindowIsNotScaled(target_xid) | ||
1002 | 108 | self.assertWindowIsClosed(target_xid) | ||
1003 | 109 | |||
1004 | 110 | def test_scaled_window_closes_on_close_button_click(self): | ||
1005 | 111 | """Test that a window is closed when its close button is clicked in spread""" | ||
1006 | 112 | win = self.start_test_application_windows("Calculator", 1)[0] | ||
1007 | 113 | self.initiate_spread_for_screen() | ||
1008 | 114 | |||
1009 | 115 | target_xid = win.x_id | ||
1010 | 116 | [target_win] = [w for w in self.screen.scaled_windows if w.xid == target_xid] | ||
1011 | 117 | |||
1012 | 118 | (x, y, w, h) = target_win.scale_close_geometry | ||
1013 | 119 | self.mouse.move(x + w / 2, y + h / 2) | ||
1014 | 120 | sleep(.5) | ||
1015 | 121 | self.mouse.click() | ||
1016 | 122 | |||
1017 | 123 | self.assertWindowIsNotScaled(target_xid) | ||
1018 | 124 | self.assertWindowIsClosed(target_xid) |
Code looks good, tests work, bugs look fixed and also works manually :). +1