Merge lp:~3v1n0/unity/application-manager-new into lp:unity
- application-manager-new
- Merge into trunk
Status: | Merged |
---|---|
Approved by: | Christopher Townsend |
Approved revision: | no longer in the source branch. |
Merged at revision: | 3975 |
Proposed branch: | lp:~3v1n0/unity/application-manager-new |
Merge into: | lp:unity |
Prerequisite: | lp:~3v1n0/unity/lim-everywhere |
Diff against target: |
2037 lines (+583/-507) 15 files modified
launcher/ApplicationLauncherIcon.cpp (+11/-11) launcher/MockLauncherIcon.h (+1/-1) panel/CMakeLists.txt (+1/-1) panel/PanelMenuView.cpp (+102/-251) panel/PanelMenuView.h (+11/-21) tests/mock-application.h (+15/-7) tests/test_application_launcher_icon.cpp (+5/-2) tests/test_panel_menu_view.cpp (+1/-8) tests/test_switcher_controller.h (+1/-1) tests/test_switcher_controller_class.cpp (+1/-1) unity-shared/ApplicationManager.cpp (+19/-0) unity-shared/ApplicationManager.h (+64/-6) unity-shared/BamfApplicationManager.cpp (+215/-145) unity-shared/BamfApplicationManager.h (+36/-18) unity-shared/StandaloneAppManager.cpp (+100/-34) |
To merge this branch: | bzr merge lp:~3v1n0/unity/application-manager-new |
Related bugs: |
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
Christopher Townsend | Approve | ||
PS Jenkins bot (community) | continuous-integration | Approve | |
Stephen M. Webb (community) | Needs Fixing | ||
Review via email: mp+248778@code.launchpad.net |
Commit message
ApplicationManager: add missing features, keep a copy of views around
Use this in PanelMenuView, getting rid of the BAMF internal at this level.
Description of the change
PS Jenkins bot (ps-jenkins) wrote : | # |
PS Jenkins bot (ps-jenkins) wrote : | # |
FAILED: Continuous integration, rev:3969
http://
Executed test runs:
FAILURE: http://
FAILURE: http://
FAILURE: http://
Click here to trigger a rebuild:
http://
PS Jenkins bot (ps-jenkins) wrote : | # |
FAILED: Continuous integration, rev:3972
http://
Executed test runs:
FAILURE: http://
FAILURE: http://
FAILURE: http://
Click here to trigger a rebuild:
http://
PS Jenkins bot (ps-jenkins) wrote : | # |
FAILED: Continuous integration, rev:3973
http://
Executed test runs:
FAILURE: http://
FAILURE: http://
FAILURE: http://
Click here to trigger a rebuild:
http://
PS Jenkins bot (ps-jenkins) wrote : | # |
PASSED: Continuous integration, rev:3975
http://
Executed test runs:
SUCCESS: http://
SUCCESS: http://
SUCCESS: http://
Click here to trigger a rebuild:
http://
PS Jenkins bot (ps-jenkins) wrote : | # |
PASSED: Continuous integration, rev:3976
http://
Executed test runs:
SUCCESS: http://
SUCCESS: http://
SUCCESS: http://
Click here to trigger a rebuild:
http://
Stephen M. Webb (bregma) wrote : | # |
One of the commits made after this MP was reviewd and approved cause unit test failures.
PS Jenkins bot (ps-jenkins) wrote : | # |
FAILED: Continuous integration, rev:3982
http://
Executed test runs:
FAILURE: http://
FAILURE: http://
FAILURE: http://
Click here to trigger a rebuild:
http://
PS Jenkins bot (ps-jenkins) wrote : | # |
FAILED: Continuous integration, rev:3982
http://
Executed test runs:
FAILURE: http://
FAILURE: http://
FAILURE: http://
Click here to trigger a rebuild:
http://
PS Jenkins bot (ps-jenkins) wrote : | # |
PASSED: Continuous integration, rev:3982
http://
Executed test runs:
SUCCESS: http://
SUCCESS: http://
SUCCESS: http://
Click here to trigger a rebuild:
http://
Christopher Townsend (townsend) wrote : | # |
Ok, all good now.
Preview Diff
1 | === modified file 'launcher/ApplicationLauncherIcon.cpp' |
2 | --- launcher/ApplicationLauncherIcon.cpp 2015-03-25 14:59:04 +0000 |
3 | +++ launcher/ApplicationLauncherIcon.cpp 2015-05-22 16:04:25 +0000 |
4 | @@ -156,13 +156,14 @@ |
5 | { |
6 | // Lambda functions should be fine here because when the application the icon |
7 | // is only ever removed when the application is closed. |
8 | - signals_conn_.Add(app_->window_opened.connect([this](ApplicationWindow const&) { |
9 | + signals_conn_.Add(app_->window_opened.connect([this](ApplicationWindowPtr const&) { |
10 | EnsureWindowState(); |
11 | UpdateIconGeometries(GetCenters()); |
12 | })); |
13 | |
14 | - signals_conn_.Add(app_->window_closed.connect(sigc::mem_fun(this, &ApplicationLauncherIcon::EnsureWindowState))); |
15 | - signals_conn_.Add(app_->window_moved.connect(sigc::hide(sigc::mem_fun(this, &ApplicationLauncherIcon::EnsureWindowState)))); |
16 | + auto ensure_windows_cb = sigc::hide(sigc::mem_fun(this, &ApplicationLauncherIcon::EnsureWindowState)); |
17 | + signals_conn_.Add(app_->window_closed.connect(ensure_windows_cb)); |
18 | + signals_conn_.Add(app_->window_moved.connect(ensure_windows_cb)); |
19 | |
20 | signals_conn_.Add(app_->urgent.changed.connect([this](bool const& urgent) { |
21 | LOG_DEBUG(logger) << tooltip_text() << " urgent now " << (urgent ? "true" : "false"); |
22 | @@ -235,7 +236,7 @@ |
23 | if (!SimpleLauncherIcon::GetQuirk(Quirk::ACTIVE, monitor)) |
24 | return false; |
25 | |
26 | - if (app_->type() == "webapp") |
27 | + if (app_->type() == AppType::WEBAPP) |
28 | return true; |
29 | |
30 | // Sometimes BAMF is not fast enough to update the active application |
31 | @@ -702,7 +703,7 @@ |
32 | if (window->Focus()) |
33 | return; |
34 | } |
35 | - else if (app_->type() == "webapp") |
36 | + else if (app_->type() == AppType::WEBAPP) |
37 | { |
38 | // Webapps are again special. |
39 | OpenInstanceLauncherIcon(arg.timestamp); |
40 | @@ -837,8 +838,6 @@ |
41 | if (windows.size() < 2) |
42 | return; |
43 | |
44 | - Window active = WindowManager::Default().GetActiveWindow(); |
45 | - |
46 | // add menu items for all open windows |
47 | for (auto const& w : windows) |
48 | { |
49 | @@ -862,7 +861,7 @@ |
50 | wm.Raise(xid); |
51 | }); |
52 | |
53 | - if (xid == active) |
54 | + if (w->active()) |
55 | { |
56 | dbusmenu_menuitem_property_set(menu_item, DBUSMENU_MENUITEM_PROP_TOGGLE_TYPE, DBUSMENU_MENUITEM_TOGGLE_RADIO); |
57 | dbusmenu_menuitem_property_set_int(menu_item, DBUSMENU_MENUITEM_PROP_TOGGLE_STATE, DBUSMENU_MENUITEM_TOGGLE_STATE_CHECKED); |
58 | @@ -1113,7 +1112,7 @@ |
59 | |
60 | void ApplicationLauncherIcon::UpdateIconGeometries(std::vector<nux::Point3> const& centers) |
61 | { |
62 | - if (app_->type() == "webapp") |
63 | + if (app_->type() == AppType::WEBAPP) |
64 | return; |
65 | |
66 | nux::Geometry geo(0, 0, icon_size, icon_size); |
67 | @@ -1189,6 +1188,7 @@ |
68 | auto const& desktop_file = DesktopFile(); |
69 | |
70 | return boost::algorithm::ends_with(desktop_file, "org.gnome.Nautilus.desktop") || |
71 | + boost::algorithm::ends_with(desktop_file, "nautilus.desktop") || |
72 | boost::algorithm::ends_with(desktop_file, "nautilus-folder-handler.desktop") || |
73 | boost::algorithm::ends_with(desktop_file, "nautilus-home.desktop"); |
74 | } |
75 | @@ -1264,14 +1264,14 @@ |
76 | |
77 | bool ApplicationLauncherIcon::AllowDetailViewInSwitcher() const |
78 | { |
79 | - return app_->type() != "webapp"; |
80 | + return app_->type() != AppType::WEBAPP; |
81 | } |
82 | |
83 | uint64_t ApplicationLauncherIcon::SwitcherPriority() |
84 | { |
85 | uint64_t result = 0; |
86 | // Webapps always go at the back. |
87 | - if (app_->type() == "webapp") |
88 | + if (app_->type() == AppType::WEBAPP) |
89 | return result; |
90 | |
91 | for (auto& window : app_->GetWindows()) |
92 | |
93 | === modified file 'launcher/MockLauncherIcon.h' |
94 | --- launcher/MockLauncherIcon.h 2015-03-20 16:23:04 +0000 |
95 | +++ launcher/MockLauncherIcon.h 2015-05-22 16:04:25 +0000 |
96 | @@ -52,7 +52,7 @@ |
97 | icon.SetGetterFunction([this] { return ""; }); |
98 | } |
99 | |
100 | - virtual std::string type() const { return "mock"; } |
101 | + virtual WindowType type() const { return WindowType::UNKNOWN; } |
102 | |
103 | virtual Window window_id() const { return xid_; } |
104 | virtual int monitor() const { return -1; } |
105 | |
106 | === modified file 'panel/CMakeLists.txt' |
107 | --- panel/CMakeLists.txt 2014-02-12 07:13:01 +0000 |
108 | +++ panel/CMakeLists.txt 2015-05-22 16:04:25 +0000 |
109 | @@ -36,4 +36,4 @@ |
110 | # |
111 | add_executable (panel StandalonePanel.cpp) |
112 | find_library (COMPIZ_LIB compiz_core ${COMPIZ_LIBDIR}) |
113 | -target_link_libraries (panel panel-lib unity-shared unity-shared-standalone ${COMPIZ_LIB}) |
114 | +target_link_libraries (panel panel-lib unity-shared unity-shared-standalone unity-shared-bamf ${COMPIZ_LIB}) |
115 | |
116 | === modified file 'panel/PanelMenuView.cpp' |
117 | --- panel/PanelMenuView.cpp 2015-02-19 14:19:44 +0000 |
118 | +++ panel/PanelMenuView.cpp 2015-05-22 16:04:25 +0000 |
119 | @@ -20,6 +20,7 @@ |
120 | |
121 | #include <Nux/Nux.h> |
122 | #include <NuxCore/Logger.h> |
123 | +#include <UnityCore/GLibWrapper.h> |
124 | #include <boost/algorithm/string/erase.hpp> |
125 | |
126 | #include "PanelMenuView.h" |
127 | @@ -87,13 +88,11 @@ |
128 | , maximized_window(0) |
129 | , focused(true) |
130 | , menu_manager_(menus) |
131 | - , matcher_(bamf_matcher_get_default()) |
132 | , is_inside_(false) |
133 | , is_grabbed_(false) |
134 | , is_maximized_(false) |
135 | , is_desktop_focused_(false) |
136 | , last_active_view_(nullptr) |
137 | - , new_application_(nullptr) |
138 | , switcher_showing_(false) |
139 | , spread_showing_(false) |
140 | , launcher_keynav_(false) |
141 | @@ -105,9 +104,8 @@ |
142 | , always_show_menus_(menu_manager_->always_show_menus()) |
143 | , desktop_name_(get_current_desktop()) |
144 | { |
145 | - BamfWindow* active_win = bamf_matcher_get_active_window(matcher_); |
146 | - if (BAMF_IS_WINDOW(active_win)) |
147 | - active_window = bamf_window_get_xid(active_win); |
148 | + if (ApplicationWindowPtr const& win = ApplicationManager::Default().GetActiveWindow()) |
149 | + active_window = win->window_id(); |
150 | |
151 | SetupWindowButtons(); |
152 | SetupTitlebarGrabArea(); |
153 | @@ -117,8 +115,7 @@ |
154 | |
155 | opacity = 0.0f; |
156 | |
157 | - if (Refresh()) |
158 | - FullRedraw(); |
159 | + RefreshAndRedraw(); |
160 | } |
161 | |
162 | PanelMenuView::~PanelMenuView() |
163 | @@ -144,14 +141,11 @@ |
164 | |
165 | void PanelMenuView::SetupPanelMenuViewSignals() |
166 | { |
167 | - active_win_changed_signal_.Connect(matcher_, "active-window-changed", |
168 | - sigc::mem_fun(this, &PanelMenuView::OnActiveWindowChanged)); |
169 | - active_app_changed_signal_.Connect(matcher_, "active-application-changed", |
170 | - sigc::mem_fun(this, &PanelMenuView::OnActiveAppChanged)); |
171 | - view_opened_signal_.Connect(matcher_, "view-opened", |
172 | - sigc::mem_fun(this, &PanelMenuView::OnViewOpened)); |
173 | - view_closed_signal_.Connect(matcher_, "view-closed", |
174 | - sigc::mem_fun(this, &PanelMenuView::OnViewClosed)); |
175 | + auto& am = ApplicationManager::Default(); |
176 | + am.active_window_changed.connect(sigc::mem_fun(this, &PanelMenuView::OnActiveWindowChanged)); |
177 | + am.active_application_changed.connect(sigc::mem_fun(this, &PanelMenuView::OnActiveAppChanged)); |
178 | + am.application_started.connect(sigc::mem_fun(this, &PanelMenuView::OnApplicationStarted)); |
179 | + am.application_stopped.connect(sigc::mem_fun(this, &PanelMenuView::OnApplicationClosed)); |
180 | |
181 | mouse_enter.connect(sigc::mem_fun(this, &PanelMenuView::OnPanelViewMouseEnter)); |
182 | mouse_leave.connect(sigc::mem_fun(this, &PanelMenuView::OnPanelViewMouseLeave)); |
183 | @@ -232,9 +226,9 @@ |
184 | wm.window_resized.connect(sigc::mem_fun(this, &PanelMenuView::OnWindowMoved)); |
185 | wm.initiate_spread.connect(sigc::mem_fun(this, &PanelMenuView::OnSpreadInitiate)); |
186 | wm.terminate_spread.connect(sigc::mem_fun(this, &PanelMenuView::OnSpreadTerminate)); |
187 | - wm.initiate_expo.connect(sigc::mem_fun(this, &PanelMenuView::OnExpoInitiate)); |
188 | - wm.terminate_expo.connect(sigc::mem_fun(this, &PanelMenuView::OnExpoTerminate)); |
189 | - wm.screen_viewport_switch_ended.connect(sigc::mem_fun(this, &PanelMenuView::OnExpoTerminate)); |
190 | + wm.initiate_expo.connect(sigc::mem_fun(this, &PanelMenuView::RefreshAndRedraw)); |
191 | + wm.terminate_expo.connect(sigc::mem_fun(this, &PanelMenuView::RefreshAndRedraw)); |
192 | + wm.screen_viewport_switch_ended.connect(sigc::mem_fun(this, &PanelMenuView::RefreshAndRedraw)); |
193 | } |
194 | |
195 | void PanelMenuView::SetupUBusManagerInterests() |
196 | @@ -300,7 +294,7 @@ |
197 | void PanelMenuView::OnLIMChanged(bool lim) |
198 | { |
199 | integrated_menus_ = lim; |
200 | - new_application_ = nullptr; |
201 | + new_application_.reset(); |
202 | |
203 | if (!integrated_menus_) |
204 | { |
205 | @@ -321,7 +315,7 @@ |
206 | if (!always_show_menus_) |
207 | CheckMouseInside(); |
208 | |
209 | - FullRedraw(); |
210 | + QueueDraw(); |
211 | } |
212 | |
213 | nux::Area* PanelMenuView::FindAreaUnderMouse(const nux::Point& mouse_position, nux::NuxEventType event_type) |
214 | @@ -762,41 +756,13 @@ |
215 | std::string PanelMenuView::GetActiveViewName(bool use_appname) const |
216 | { |
217 | std::string label; |
218 | - BamfWindow* window; |
219 | - |
220 | - window = bamf_matcher_get_active_window(matcher_); |
221 | - |
222 | - if (BAMF_IS_WINDOW(window)) |
223 | + auto& am = ApplicationManager::Default(); |
224 | + |
225 | + if (ApplicationWindowPtr const& window = am.GetActiveWindow()) |
226 | { |
227 | - BamfView *view = reinterpret_cast<BamfView*>(window); |
228 | - Window window_xid = bamf_window_get_xid(window); |
229 | - |
230 | - if (bamf_window_get_window_type(window) == BAMF_WINDOW_DOCK) |
231 | - { |
232 | - auto panel = const_cast<PanelMenuView*>(this)->GetTopLevelViewWindow(); |
233 | - if (static_cast<nux::BaseWindow*>(panel)->GetInputWindowId() == window_xid) |
234 | - return desktop_name_; |
235 | - |
236 | - std::vector<Window> const& our_xids = nux::XInputWindow::NativeHandleList(); |
237 | - |
238 | - if (std::find(our_xids.begin(), our_xids.end(), window_xid) != our_xids.end()) |
239 | - { |
240 | - /* If the active window is an unity window, we need to fallback to the |
241 | - * top one, anyway we should always avoid to focus unity internal windows */ |
242 | - BamfWindow* top_win = GetBamfWindowForXid(GetTopWindow()); |
243 | - |
244 | - if (top_win && top_win != window) |
245 | - { |
246 | - window = top_win; |
247 | - } |
248 | - else |
249 | - { |
250 | - return ""; |
251 | - } |
252 | - } |
253 | - } |
254 | - |
255 | - if (bamf_window_get_window_type(window) == BAMF_WINDOW_DESKTOP) |
256 | + Window window_xid = window->window_id(); |
257 | + |
258 | + if (window->type() == WindowType::DESKTOP) |
259 | { |
260 | label = desktop_name_; |
261 | } |
262 | @@ -806,27 +772,16 @@ |
263 | } |
264 | |
265 | if (WindowManager::Default().IsWindowMaximized(window_xid) && !use_appname) |
266 | - { |
267 | - label = glib::String(bamf_view_get_name(view)).Str(); |
268 | - } |
269 | - |
270 | - if (label.empty()) |
271 | - { |
272 | - BamfApplication* app; |
273 | - app = bamf_matcher_get_application_for_window(matcher_, window); |
274 | - |
275 | - if (BAMF_IS_APPLICATION(app)) |
276 | - { |
277 | - view = reinterpret_cast<BamfView*>(app); |
278 | - label = glib::String(bamf_view_get_name(view)).Str(); |
279 | - } |
280 | - } |
281 | - |
282 | - if (label.empty()) |
283 | - { |
284 | - view = reinterpret_cast<BamfView*>(window); |
285 | - label = glib::String(bamf_view_get_name(view)).Str(); |
286 | - } |
287 | + label = window->title(); |
288 | + |
289 | + if (label.empty()) |
290 | + { |
291 | + if (ApplicationPtr const& app = am.GetActiveApplication()) |
292 | + label = app->title(); |
293 | + } |
294 | + |
295 | + if (label.empty()) |
296 | + label = window->title(); |
297 | } |
298 | |
299 | return label; |
300 | @@ -835,24 +790,16 @@ |
301 | std::string PanelMenuView::GetMaximizedViewName(bool use_appname) const |
302 | { |
303 | Window maximized = maximized_window(); |
304 | - BamfWindow* window = nullptr; |
305 | std::string label; |
306 | |
307 | - window = GetBamfWindowForXid(maximized); |
308 | - |
309 | - if (BAMF_IS_WINDOW(window)) |
310 | + if (ApplicationWindowPtr const& window = ApplicationManager::Default().GetWindowForId(maximized)) |
311 | { |
312 | - BamfView* view = reinterpret_cast<BamfView*>(window); |
313 | - label = glib::String(bamf_view_get_name(view)).Str(); |
314 | + label = window->title(); |
315 | |
316 | if (use_appname || label.empty()) |
317 | { |
318 | - BamfApplication* app = bamf_matcher_get_application_for_window(matcher_, window); |
319 | - |
320 | - if (BAMF_IS_APPLICATION(app)) |
321 | - view = reinterpret_cast<BamfView*>(app); |
322 | - |
323 | - label = glib::String(bamf_view_get_name(view)).Str(); |
324 | + if (ApplicationPtr const& app = window->application()) |
325 | + label = app->title(); |
326 | } |
327 | } |
328 | |
329 | @@ -963,6 +910,12 @@ |
330 | return true; |
331 | } |
332 | |
333 | +void PanelMenuView::RefreshAndRedraw() |
334 | +{ |
335 | + if (Refresh()) |
336 | + QueueDraw(); |
337 | +} |
338 | + |
339 | void PanelMenuView::OnActiveChanged(PanelIndicatorEntryView* view, bool is_active) |
340 | { |
341 | if (is_active) |
342 | @@ -977,8 +930,7 @@ |
343 | } |
344 | } |
345 | |
346 | - if (Refresh()) |
347 | - FullRedraw(); |
348 | + RefreshAndRedraw(); |
349 | } |
350 | |
351 | void PanelMenuView::OnEntryAdded(indicator::Entry::Ptr const& entry) |
352 | @@ -1012,22 +964,13 @@ |
353 | } |
354 | } |
355 | |
356 | -void PanelMenuView::OnNameChanged(BamfView* bamf_view, gchar* new_name, gchar* old_name) |
357 | -{ |
358 | - if (Refresh()) |
359 | - FullRedraw(); |
360 | -} |
361 | - |
362 | bool PanelMenuView::OnNewAppShow() |
363 | { |
364 | - BamfApplication* active_app = bamf_matcher_get_active_application(matcher_); |
365 | - new_application_ = glib::Object<BamfApplication>(active_app, glib::AddRef()); |
366 | + new_application_ = ApplicationManager::Default().GetActiveApplication(); |
367 | QueueDraw(); |
368 | |
369 | if (sources_.GetSource(NEW_APP_HIDE_TIMEOUT)) |
370 | - { |
371 | new_app_menu_shown_ = false; |
372 | - } |
373 | |
374 | auto cb_func = sigc::mem_fun(this, &PanelMenuView::OnNewAppHide); |
375 | sources_.AddTimeoutSeconds(menu_manager_->discovery(), cb_func, NEW_APP_HIDE_TIMEOUT); |
376 | @@ -1044,69 +987,51 @@ |
377 | return false; |
378 | } |
379 | |
380 | -void PanelMenuView::OnViewOpened(BamfMatcher *matcher, BamfView *view) |
381 | +void PanelMenuView::OnApplicationStarted(ApplicationPtr const& app) |
382 | { |
383 | /* FIXME: here we should also check for if the view is also user_visible |
384 | * but it seems that BAMF doesn't handle this correctly after some |
385 | * stress tests (repeated launches). */ |
386 | - if (!BAMF_IS_APPLICATION(view) || integrated_menus_) |
387 | + if (integrated_menus_) |
388 | return; |
389 | |
390 | - new_apps_.push_front(glib::Object<BamfApplication>(BAMF_APPLICATION(view), glib::AddRef())); |
391 | + new_apps_.push_front(app); |
392 | } |
393 | |
394 | -void PanelMenuView::OnApplicationClosed(BamfApplication* app) |
395 | +void PanelMenuView::OnApplicationClosed(ApplicationPtr const& app) |
396 | { |
397 | - if (BAMF_IS_APPLICATION(app) && !integrated_menus_) |
398 | + if (app && !integrated_menus_) |
399 | { |
400 | if (std::find(new_apps_.begin(), new_apps_.end(), app) != new_apps_.end()) |
401 | { |
402 | - new_apps_.remove(glib::Object<BamfApplication>(app, glib::AddRef())); |
403 | + new_apps_.remove(app); |
404 | } |
405 | else if (new_apps_.empty()) |
406 | { |
407 | - new_application_ = nullptr; |
408 | + new_application_.reset(); |
409 | } |
410 | } |
411 | |
412 | if (app == new_application_) |
413 | { |
414 | - new_application_ = nullptr; |
415 | - } |
416 | -} |
417 | - |
418 | -void PanelMenuView::OnViewClosed(BamfMatcher *matcher, BamfView *view) |
419 | -{ |
420 | - if (reinterpret_cast<BamfView*>(view_name_changed_signal_.object()) == view) |
421 | - { |
422 | - view_name_changed_signal_.Disconnect(); |
423 | - } |
424 | - |
425 | - if (BAMF_IS_APPLICATION(view)) |
426 | - { |
427 | - OnApplicationClosed(reinterpret_cast<BamfApplication*>(view)); |
428 | - } |
429 | - else if (reinterpret_cast<BamfApplication*>(view) == new_application_) |
430 | - { |
431 | - new_application_ = nullptr; |
432 | - } |
433 | - else if (BAMF_IS_WINDOW(view)) |
434 | - { |
435 | - /* FIXME, this can be removed when window_unmapped WindowManager signal |
436 | - * will emit the proper xid */ |
437 | - Window xid = bamf_window_get_xid(reinterpret_cast<BamfWindow*>(view)); |
438 | - OnWindowUnmapped(xid); |
439 | - } |
440 | -} |
441 | - |
442 | -void PanelMenuView::OnActiveAppChanged(BamfMatcher *matcher, |
443 | - BamfApplication* old_app, |
444 | - BamfApplication* new_app) |
445 | -{ |
446 | - if (BAMF_IS_APPLICATION(new_app)) |
447 | - { |
448 | - app_name_changed_signal_.Connect(BAMF_VIEW(new_app), "name-changed", |
449 | - sigc::mem_fun(this, &PanelMenuView::OnNameChanged)); |
450 | + new_application_.reset(); |
451 | + } |
452 | +} |
453 | + |
454 | +void PanelMenuView::OnWindowClosed(ApplicationWindowPtr const& win) |
455 | +{ |
456 | + /* FIXME, this can be removed when window_unmapped WindowManager signal |
457 | + * will emit the proper xid */ |
458 | + OnWindowUnmapped(win->window_id()); |
459 | +} |
460 | + |
461 | +void PanelMenuView::OnActiveAppChanged(ApplicationPtr const& new_app) |
462 | +{ |
463 | + if (new_app) |
464 | + { |
465 | + app_name_changed_conn_ = new_app->title.changed.connect([this] (std::string const&t) { |
466 | + RefreshAndRedraw(); |
467 | + }); |
468 | |
469 | if (integrated_menus_ || always_show_menus_) |
470 | return; |
471 | @@ -1140,7 +1065,7 @@ |
472 | } |
473 | } |
474 | |
475 | -void PanelMenuView::OnActiveWindowChanged(BamfMatcher *matcher, BamfView* old_view, BamfView* new_view) |
476 | +void PanelMenuView::OnActiveWindowChanged(ApplicationWindowPtr const& new_win) |
477 | { |
478 | show_now_activated_ = false; |
479 | is_maximized_ = false; |
480 | @@ -1149,13 +1074,12 @@ |
481 | |
482 | sources_.Remove(WINDOW_MOVED_TIMEOUT); |
483 | |
484 | - if (BAMF_IS_WINDOW(new_view)) |
485 | + if (new_win) |
486 | { |
487 | - BamfWindow* window = reinterpret_cast<BamfWindow*>(new_view); |
488 | - active_xid = bamf_window_get_xid(window); |
489 | - is_maximized_ = (bamf_window_maximized(window) == BAMF_WINDOW_MAXIMIZED); |
490 | + active_xid = new_win->window_id(); |
491 | + is_maximized_ = new_win->maximized(); |
492 | |
493 | - if (bamf_window_get_window_type(window) == BAMF_WINDOW_DESKTOP) |
494 | + if (new_win->type() == WindowType::DESKTOP) |
495 | { |
496 | is_desktop_focused_ = !maximized_window(); |
497 | we_control_active_ = true; |
498 | @@ -1173,14 +1097,13 @@ |
499 | } |
500 | |
501 | // register callback for new view |
502 | - view_name_changed_signal_.Connect(new_view, "name-changed", |
503 | - sigc::mem_fun(this, &PanelMenuView::OnNameChanged)); |
504 | + win_name_changed_conn_ = new_win->title.changed.connect([this] (std::string const& t) { |
505 | + RefreshAndRedraw(); |
506 | + }); |
507 | } |
508 | |
509 | active_window = active_xid; |
510 | - |
511 | - if (Refresh()) |
512 | - FullRedraw(); |
513 | + RefreshAndRedraw(); |
514 | } |
515 | |
516 | void PanelMenuView::OnSpreadInitiate() |
517 | @@ -1195,18 +1118,6 @@ |
518 | QueueDraw(); |
519 | } |
520 | |
521 | -void PanelMenuView::OnExpoInitiate() |
522 | -{ |
523 | - if (Refresh()) |
524 | - QueueDraw(); |
525 | -} |
526 | - |
527 | -void PanelMenuView::OnExpoTerminate() |
528 | -{ |
529 | - if (Refresh()) |
530 | - QueueDraw(); |
531 | -} |
532 | - |
533 | void PanelMenuView::OnWindowMinimized(Window xid) |
534 | { |
535 | maximized_wins_.erase(std::remove(maximized_wins_.begin(), maximized_wins_.end(), xid), maximized_wins_.end()); |
536 | @@ -1214,13 +1125,11 @@ |
537 | |
538 | if (xid == active_window()) |
539 | { |
540 | - if (Refresh()) |
541 | - QueueDraw(); |
542 | + RefreshAndRedraw(); |
543 | } |
544 | else if (integrated_menus_ && window_buttons_->controlled_window == xid) |
545 | { |
546 | - if (Refresh()) |
547 | - QueueDraw(); |
548 | + RefreshAndRedraw(); |
549 | } |
550 | } |
551 | |
552 | @@ -1234,8 +1143,7 @@ |
553 | UpdateMaximizedWindow(); |
554 | } |
555 | |
556 | - if (Refresh()) |
557 | - QueueDraw(); |
558 | + RefreshAndRedraw(); |
559 | } |
560 | else |
561 | { |
562 | @@ -1247,8 +1155,7 @@ |
563 | |
564 | if (integrated_menus_ && IsWindowUnderOurControl(xid)) |
565 | { |
566 | - if (Refresh()) |
567 | - QueueDraw(); |
568 | + RefreshAndRedraw(); |
569 | } |
570 | } |
571 | } |
572 | @@ -1262,13 +1169,11 @@ |
573 | |
574 | if (xid == active_window()) |
575 | { |
576 | - if (Refresh()) |
577 | - QueueDraw(); |
578 | + RefreshAndRedraw(); |
579 | } |
580 | else if (integrated_menus_ && window_buttons_->controlled_window == xid) |
581 | { |
582 | - if (Refresh()) |
583 | - QueueDraw(); |
584 | + RefreshAndRedraw(); |
585 | } |
586 | } |
587 | |
588 | @@ -1281,8 +1186,7 @@ |
589 | maximized_wins_.push_front(xid); |
590 | UpdateMaximizedWindow(); |
591 | |
592 | - if (Refresh()) |
593 | - QueueDraw(); |
594 | + RefreshAndRedraw(); |
595 | } |
596 | else |
597 | { |
598 | @@ -1303,8 +1207,7 @@ |
599 | CheckMouseInside(); |
600 | is_maximized_ = true; |
601 | |
602 | - if (Refresh()) |
603 | - FullRedraw(); |
604 | + RefreshAndRedraw(); |
605 | } |
606 | else |
607 | { |
608 | @@ -1313,8 +1216,7 @@ |
609 | |
610 | if (integrated_menus_ && IsWindowUnderOurControl(xid)) |
611 | { |
612 | - if (Refresh()) |
613 | - QueueDraw(); |
614 | + RefreshAndRedraw(); |
615 | } |
616 | } |
617 | } |
618 | @@ -1328,14 +1230,11 @@ |
619 | { |
620 | is_maximized_ = false; |
621 | is_grabbed_ = false; |
622 | - |
623 | - if (Refresh()) |
624 | - FullRedraw(); |
625 | + RefreshAndRedraw(); |
626 | } |
627 | else if (integrated_menus_ && window_buttons_->controlled_window == xid) |
628 | { |
629 | - if (Refresh()) |
630 | - QueueDraw(); |
631 | + RefreshAndRedraw(); |
632 | } |
633 | } |
634 | |
635 | @@ -1350,8 +1249,7 @@ |
636 | if (HasVisibleMenus()) |
637 | on_indicator_updated.emit(); |
638 | |
639 | - if (Refresh()) |
640 | - QueueDraw(); |
641 | + RefreshAndRedraw(); |
642 | } |
643 | |
644 | return false; |
645 | @@ -1436,55 +1334,20 @@ |
646 | Window PanelMenuView::GetTopWindow() const |
647 | { |
648 | Window window_xid = 0; |
649 | - GList* windows = bamf_matcher_get_window_stack_for_monitor(matcher_, monitor_); |
650 | |
651 | - for (GList* l = windows; l; l = l->next) |
652 | + for (auto const& win : ApplicationManager::Default().GetWindowsForMonitor(monitor_)) |
653 | { |
654 | - if (!BAMF_IS_WINDOW(l->data)) |
655 | - continue; |
656 | - |
657 | - Window xid = bamf_window_get_xid(static_cast<BamfWindow*>(l->data)); |
658 | - bool visible = bamf_view_is_user_visible(static_cast<BamfView*>(l->data)); |
659 | - |
660 | - if (visible && IsValidWindow(xid)) |
661 | + Window xid = win->window_id(); |
662 | + |
663 | + if (win->visible() && IsValidWindow(xid)) |
664 | { |
665 | window_xid = xid; |
666 | } |
667 | } |
668 | |
669 | - g_list_free(windows); |
670 | - |
671 | return window_xid; |
672 | } |
673 | |
674 | -BamfWindow* PanelMenuView::GetBamfWindowForXid(Window xid) const |
675 | -{ |
676 | - BamfWindow* window = nullptr; |
677 | - |
678 | - if (xid != 0) |
679 | - { |
680 | - GList* windows = bamf_matcher_get_windows(matcher_); |
681 | - |
682 | - for (GList* l = windows; l; l = l->next) |
683 | - { |
684 | - if (!BAMF_IS_WINDOW(l->data)) |
685 | - continue; |
686 | - |
687 | - auto win = static_cast<BamfWindow*>(l->data); |
688 | - |
689 | - if (bamf_window_get_xid(win) == xid) |
690 | - { |
691 | - window = win; |
692 | - break; |
693 | - } |
694 | - } |
695 | - |
696 | - g_list_free(windows); |
697 | - } |
698 | - |
699 | - return window; |
700 | -} |
701 | - |
702 | void PanelMenuView::ActivateIntegratedMenus(nux::Point const& click) |
703 | { |
704 | if (!layout_->GetAbsoluteGeometry().IsInside(click)) |
705 | @@ -1679,8 +1542,7 @@ |
706 | |
707 | is_inside_ = true; |
708 | is_grabbed_ = true; |
709 | - if (Refresh()) |
710 | - FullRedraw(); |
711 | + RefreshAndRedraw(); |
712 | |
713 | /* Ungrab the pointer and start the X move, to make the decorator handle it */ |
714 | titlebar_grab_area_->SetGrabbed(false); |
715 | @@ -1700,8 +1562,7 @@ |
716 | if (!is_inside_) |
717 | is_grabbed_ = false; |
718 | |
719 | - if (Refresh()) |
720 | - FullRedraw(); |
721 | + RefreshAndRedraw(); |
722 | } |
723 | |
724 | // Introspectable |
725 | @@ -1763,8 +1624,7 @@ |
726 | show_now_activated_ = false; |
727 | } |
728 | |
729 | - if (Refresh()) |
730 | - QueueDraw(); |
731 | + RefreshAndRedraw(); |
732 | } |
733 | |
734 | void PanelMenuView::OnLauncherKeyNavStarted(GVariant* data) |
735 | @@ -1785,9 +1645,7 @@ |
736 | |
737 | launcher_keynav_ = false; |
738 | CheckMouseInside(); |
739 | - |
740 | - if (Refresh()) |
741 | - QueueDraw(); |
742 | + RefreshAndRedraw(); |
743 | } |
744 | |
745 | void PanelMenuView::OnLauncherSelectionChanged(GVariant* data) |
746 | @@ -1854,23 +1712,17 @@ |
747 | |
748 | maximized_wins_.clear(); |
749 | monitor_geo_ = UScreen::GetDefault()->GetMonitorGeometry(monitor_); |
750 | - GList* windows = bamf_matcher_get_window_stack_for_monitor(matcher_, monitor_); |
751 | |
752 | - for (GList* l = windows; l; l = l->next) |
753 | + for (auto const& win : ApplicationManager::Default().GetWindowsForMonitor(monitor_)) |
754 | { |
755 | - if (!BAMF_IS_WINDOW(l->data)) |
756 | - continue; |
757 | - |
758 | - auto window = static_cast<BamfWindow*>(l->data); |
759 | - auto view = static_cast<BamfView*>(l->data); |
760 | - auto xid = bamf_window_get_xid(window); |
761 | - |
762 | - if (bamf_view_is_active(view)) |
763 | + auto xid = win->window_id(); |
764 | + |
765 | + if (win->active()) |
766 | active_window = xid; |
767 | |
768 | - if (bamf_window_maximized(window) == BAMF_WINDOW_MAXIMIZED) |
769 | + if (win->maximized()) |
770 | { |
771 | - if (xid == active_window()) |
772 | + if (win->active()) |
773 | maximized_wins_.push_front(xid); |
774 | else |
775 | maximized_wins_.push_back(xid); |
776 | @@ -1881,7 +1733,6 @@ |
777 | UpdateMaximizedWindow(); |
778 | |
779 | OnStyleChanged(); |
780 | - g_list_free(windows); |
781 | } |
782 | |
783 | bool PanelMenuView::HasMenus() const |
784 | |
785 | === modified file 'panel/PanelMenuView.h' |
786 | --- panel/PanelMenuView.h 2015-02-04 09:54:49 +0000 |
787 | +++ panel/PanelMenuView.h 2015-05-22 16:04:25 +0000 |
788 | @@ -22,12 +22,11 @@ |
789 | #define PANEL_MENU_VIEW_H |
790 | |
791 | #include <NuxCore/Animation.h> |
792 | -#include <UnityCore/GLibWrapper.h> |
793 | #include <UnityCore/GLibSignal.h> |
794 | -#include <libbamf/libbamf.h> |
795 | |
796 | #include "PanelIndicatorsView.h" |
797 | #include "PanelTitlebarGrabAreaView.h" |
798 | +#include "unity-shared/ApplicationManager.h" |
799 | #include "unity-shared/MenuManager.h" |
800 | #include "unity-shared/StaticCairoText.h" |
801 | #include "unity-shared/WindowButtons.h" |
802 | @@ -88,20 +87,17 @@ |
803 | |
804 | void OnActiveChanged(PanelIndicatorEntryView* view, bool is_active); |
805 | void OnEntryViewAdded(PanelIndicatorEntryView* view); |
806 | - void OnViewOpened(BamfMatcher* matcher, BamfView* view); |
807 | - void OnViewClosed(BamfMatcher* matcher, BamfView* view); |
808 | - void OnApplicationClosed(BamfApplication* app); |
809 | - void OnActiveWindowChanged(BamfMatcher* matcher, BamfView* old_view, BamfView* new_view); |
810 | - void OnActiveAppChanged(BamfMatcher* matcher, BamfApplication* old_app, BamfApplication* new_app); |
811 | - void OnNameChanged(BamfView* bamf_view, gchar* new_name, gchar* old_name); |
812 | + void OnApplicationStarted(ApplicationPtr const&); |
813 | + void OnApplicationClosed(ApplicationPtr const&); |
814 | + void OnWindowClosed(ApplicationWindowPtr const&); |
815 | + void OnActiveWindowChanged(ApplicationWindowPtr const&); |
816 | + void OnActiveAppChanged(ApplicationPtr const&); |
817 | void OnStyleChanged(); |
818 | void OnLIMChanged(bool); |
819 | void OnAlwaysShowMenusChanged(bool); |
820 | |
821 | void OnSpreadInitiate(); |
822 | void OnSpreadTerminate(); |
823 | - void OnExpoInitiate(); |
824 | - void OnExpoTerminate(); |
825 | void OnWindowMinimized(Window xid); |
826 | void OnWindowUnminimized(Window xid); |
827 | void OnWindowUnmapped(Window xid); |
828 | @@ -122,6 +118,7 @@ |
829 | void FullRedraw(); |
830 | std::string GetCurrentTitle() const; |
831 | bool Refresh(bool force = false); |
832 | + void RefreshAndRedraw(); |
833 | |
834 | void UpdateTitleTexture(nux::Geometry const&, std::string const& label); |
835 | void UpdateLastGeometry(nux::Geometry const& geo); |
836 | @@ -131,8 +128,6 @@ |
837 | void OnPanelViewMouseEnter(int x, int y, unsigned long mouse_button_state, unsigned long special_keys_state); |
838 | void OnPanelViewMouseLeave(int x, int y, unsigned long mouse_button_state, unsigned long special_keys_state); |
839 | |
840 | - BamfWindow* GetBamfWindowForXid(Window xid) const; |
841 | - |
842 | void OnSwitcherShown(GVariant* data); |
843 | void OnLauncherKeyNavStarted(GVariant* data); |
844 | void OnLauncherKeyNavEnded(GVariant* data); |
845 | @@ -164,7 +159,6 @@ |
846 | void ActivateIntegratedMenus(nux::Point const&); |
847 | |
848 | menu::Manager::Ptr menu_manager_; |
849 | - glib::Object<BamfMatcher> matcher_; |
850 | |
851 | nux::TextureLayer* title_layer_; |
852 | nux::ObjectPtr<WindowButtons> window_buttons_; |
853 | @@ -179,8 +173,8 @@ |
854 | |
855 | PanelIndicatorEntryView* last_active_view_; |
856 | std::deque<Window> maximized_wins_; |
857 | - glib::Object<BamfApplication> new_application_; |
858 | - std::list<glib::Object<BamfApplication>> new_apps_; |
859 | + ApplicationPtr new_application_; |
860 | + std::list<ApplicationPtr> new_apps_; |
861 | std::string panel_title_; |
862 | nux::Geometry last_geo_; |
863 | nux::Geometry title_geo_; |
864 | @@ -198,12 +192,8 @@ |
865 | nux::Geometry monitor_geo_; |
866 | const std::string desktop_name_; |
867 | |
868 | - glib::Signal<void, BamfMatcher*, BamfView*> view_opened_signal_; |
869 | - glib::Signal<void, BamfMatcher*, BamfView*> view_closed_signal_; |
870 | - glib::Signal<void, BamfMatcher*, BamfView*, BamfView*> active_win_changed_signal_; |
871 | - glib::Signal<void, BamfMatcher*, BamfApplication*, BamfApplication*> active_app_changed_signal_; |
872 | - glib::Signal<void, BamfView*, gchar*, gchar*> view_name_changed_signal_; |
873 | - glib::Signal<void, BamfView*, gchar*, gchar*> app_name_changed_signal_; |
874 | + connection::Wrapper app_name_changed_conn_; |
875 | + connection::Wrapper win_name_changed_conn_; |
876 | |
877 | UBusManager ubus_manager_; |
878 | glib::SourceManager sources_; |
879 | |
880 | === modified file 'tests/mock-application.h' |
881 | --- tests/mock-application.h 2015-02-03 09:46:48 +0000 |
882 | +++ tests/mock-application.h 2015-05-22 16:04:25 +0000 |
883 | @@ -40,8 +40,8 @@ |
884 | MockApplicationWindow(Window xid) |
885 | : xid_(xid) |
886 | , monitor_(0) |
887 | + , type_(unity::WindowType::MOCK) |
888 | , title_("MockApplicationWindow "+std::to_string(xid_)) |
889 | - , type_("window") |
890 | , visible_(true) |
891 | , active_(false) |
892 | , urgent_(false) |
893 | @@ -61,26 +61,28 @@ |
894 | |
895 | Window xid_; |
896 | int monitor_; |
897 | + unity::WindowType type_; |
898 | std::string title_; |
899 | std::string icon_; |
900 | - std::string type_; |
901 | |
902 | bool visible_; |
903 | bool active_; |
904 | bool urgent_; |
905 | |
906 | - MOCK_CONST_METHOD0(type, std::string()); |
907 | + MOCK_CONST_METHOD0(type, unity::WindowType()); |
908 | MOCK_CONST_METHOD0(window_id, Window()); |
909 | MOCK_CONST_METHOD0(monitor, int()); |
910 | MOCK_CONST_METHOD0(application, unity::ApplicationPtr()); |
911 | MOCK_CONST_METHOD0(Focus, bool()); |
912 | MOCK_CONST_METHOD0(Quit, void()); |
913 | |
914 | - virtual bool LocalFocus() const |
915 | + bool LocalFocus() |
916 | { |
917 | auto& wm = unity::WindowManager::Default(); |
918 | wm.Raise(xid_); |
919 | wm.Activate(xid_); |
920 | + active_ = true; |
921 | + active.changed.emit(active_); |
922 | return true; |
923 | } |
924 | |
925 | @@ -124,7 +126,7 @@ |
926 | , active_(false) |
927 | , running_(false) |
928 | , urgent_(false) |
929 | - , type_("mock") |
930 | + , type_(unity::AppType::MOCK) |
931 | { |
932 | seen.SetSetterFunction(sigc::mem_fun(this, &MockApplication::SetSeen)); |
933 | sticky.SetSetterFunction(sigc::mem_fun(this, &MockApplication::SetSticky)); |
934 | @@ -159,10 +161,10 @@ |
935 | bool running_; |
936 | bool urgent_; |
937 | unity::WindowList windows_; |
938 | - std::string type_; |
939 | + unity::AppType type_; |
940 | std::vector<std::pair<unity::ApplicationEventType, unity::ApplicationSubjectPtr>> actions_log_; |
941 | |
942 | - MOCK_CONST_METHOD0(type, std::string()); |
943 | + MOCK_CONST_METHOD0(type, unity::AppType()); |
944 | MOCK_CONST_METHOD0(repr, std::string()); |
945 | MOCK_CONST_METHOD0(desktop_id, std::string()); |
946 | MOCK_CONST_METHOD0(GetWindows, unity::WindowList()); |
947 | @@ -306,6 +308,9 @@ |
948 | ON_CALL(*this, GetActiveWindow()).WillByDefault(Invoke([this] { return unity::ApplicationWindowPtr(); } )); |
949 | ON_CALL(*this, GetRunningApplications()).WillByDefault(Invoke([this] { return unity::ApplicationList(); } )); |
950 | ON_CALL(*this, GetApplicationForWindow(_)).WillByDefault(Invoke([this] (Window) { return unity::ApplicationPtr(); } )); |
951 | + ON_CALL(*this, GetActiveApplication()).WillByDefault(Invoke([this] { return unity::ApplicationPtr(); } )); |
952 | + ON_CALL(*this, GetWindowsForMonitor(_)).WillByDefault(Invoke([this] (Window) { return unity::WindowList(); } )); |
953 | + ON_CALL(*this, GetWindowForId(_)).WillByDefault(Invoke([this] (int) { return unity::ApplicationWindowPtr(); } )); |
954 | } |
955 | |
956 | static void StartApp(std::string const& desktop_file) |
957 | @@ -322,6 +327,9 @@ |
958 | MOCK_CONST_METHOD1(GetApplicationForDesktopFile, unity::ApplicationPtr(std::string const&)); |
959 | MOCK_CONST_METHOD0(GetRunningApplications, unity::ApplicationList()); |
960 | MOCK_CONST_METHOD1(GetApplicationForWindow, unity::ApplicationPtr(Window)); |
961 | + MOCK_CONST_METHOD0(GetActiveApplication, unity::ApplicationPtr()); |
962 | + MOCK_CONST_METHOD1(GetWindowsForMonitor, unity::WindowList(int)); |
963 | + MOCK_CONST_METHOD1(GetWindowForId, unity::ApplicationWindowPtr(Window)); |
964 | |
965 | unity::ApplicationPtr LocalGetApplicationForDesktopFile(std::string const& desktop_file) |
966 | { |
967 | |
968 | === modified file 'tests/test_application_launcher_icon.cpp' |
969 | --- tests/test_application_launcher_icon.cpp 2015-03-30 15:48:38 +0000 |
970 | +++ tests/test_application_launcher_icon.cpp 2015-05-22 16:04:25 +0000 |
971 | @@ -775,7 +775,10 @@ |
972 | mock_app->windows_ = { win1, win2 }; |
973 | WM->AddStandaloneWindow(wm_win1); |
974 | WM->AddStandaloneWindow(wm_win2); |
975 | + |
976 | + win2->Focus(); |
977 | ASSERT_TRUE(wm_win2->active()); |
978 | + ASSERT_TRUE(win2->active()); |
979 | |
980 | auto const& menus = mock_icon->Menus(); |
981 | auto const& menu1 = GetMenuItemWithLabel(menus, win1->title()); |
982 | @@ -1121,10 +1124,10 @@ |
983 | |
984 | TEST_F(TestApplicationLauncherIcon, AllowDetailViewInSwitcher) |
985 | { |
986 | - mock_app->type_ = "mock"; |
987 | + mock_app->type_ = AppType::NORMAL; |
988 | EXPECT_TRUE(mock_icon->AllowDetailViewInSwitcher()); |
989 | |
990 | - mock_app->type_ = "webapp"; |
991 | + mock_app->type_ = AppType::WEBAPP; |
992 | EXPECT_FALSE(mock_icon->AllowDetailViewInSwitcher()); |
993 | } |
994 | |
995 | |
996 | === modified file 'tests/test_panel_menu_view.cpp' |
997 | --- tests/test_panel_menu_view.cpp 2015-03-13 13:49:16 +0000 |
998 | +++ tests/test_panel_menu_view.cpp 2015-05-22 16:04:25 +0000 |
999 | @@ -45,13 +45,7 @@ |
1000 | { |
1001 | MockPanelMenuView(menu::Manager::Ptr const& menu_manager) |
1002 | : PanelMenuView(menu_manager) |
1003 | - { |
1004 | - view_opened_signal_.Disconnect(); |
1005 | - active_win_changed_signal_.Disconnect(); |
1006 | - active_app_changed_signal_.Disconnect(); |
1007 | - view_closed_signal_.Disconnect(); |
1008 | - maximized_wins_.clear(); |
1009 | - } |
1010 | + {} |
1011 | |
1012 | MOCK_METHOD0(QueueDraw, void()); |
1013 | MOCK_CONST_METHOD1(GetActiveViewName, std::string(bool)); |
1014 | @@ -81,7 +75,6 @@ |
1015 | panel_win->ComputeContentSize(); |
1016 | |
1017 | menu_view.SetMonitor(monitor); |
1018 | - menu_view.maximized_wins_.clear(); |
1019 | |
1020 | return panel_win; |
1021 | } |
1022 | |
1023 | === modified file 'tests/test_switcher_controller.h' |
1024 | --- tests/test_switcher_controller.h 2014-03-21 04:40:12 +0000 |
1025 | +++ tests/test_switcher_controller.h 2015-05-22 16:04:25 +0000 |
1026 | @@ -54,7 +54,7 @@ |
1027 | FakeApplicationWindow(Window xid, uint64_t active_number = 0); |
1028 | ~FakeApplicationWindow(); |
1029 | |
1030 | - virtual std::string type() const; |
1031 | + virtual WindowType type() const; |
1032 | |
1033 | virtual Window window_id() const; |
1034 | virtual int monitor() const; |
1035 | |
1036 | === modified file 'tests/test_switcher_controller_class.cpp' |
1037 | --- tests/test_switcher_controller_class.cpp 2013-10-14 17:36:51 +0000 |
1038 | +++ tests/test_switcher_controller_class.cpp 2015-05-22 16:04:25 +0000 |
1039 | @@ -41,7 +41,7 @@ |
1040 | testwrapper::StandaloneWM::Get()->Close(xid_); |
1041 | } |
1042 | |
1043 | -std::string FakeApplicationWindow::type() const { return "mock"; } |
1044 | +WindowType FakeApplicationWindow::type() const { return WindowType::MOCK; } |
1045 | |
1046 | Window FakeApplicationWindow::window_id() const { return xid_; } |
1047 | int FakeApplicationWindow::monitor() const { return -1; } |
1048 | |
1049 | === modified file 'unity-shared/ApplicationManager.cpp' |
1050 | --- unity-shared/ApplicationManager.cpp 2012-11-29 09:25:50 +0000 |
1051 | +++ unity-shared/ApplicationManager.cpp 2015-05-22 16:04:25 +0000 |
1052 | @@ -33,6 +33,25 @@ |
1053 | return *instance; |
1054 | } |
1055 | |
1056 | +bool operator==(ApplicationPtr const& lhs, ApplicationPtr const& rhs) |
1057 | +{ |
1058 | + return (lhs.get() == rhs.get() || (lhs && rhs && *lhs == *rhs)); |
1059 | +} |
1060 | + |
1061 | +bool operator!=(ApplicationPtr const& lhs, ApplicationPtr const& rhs) |
1062 | +{ |
1063 | + return !(lhs == rhs); |
1064 | +} |
1065 | + |
1066 | +bool operator==(ApplicationWindowPtr const& lhs, ApplicationWindowPtr const& rhs) |
1067 | +{ |
1068 | + return (lhs.get() == rhs.get() || (lhs && rhs && *lhs == *rhs)); |
1069 | +} |
1070 | + |
1071 | +bool operator!=(ApplicationWindowPtr const& lhs, ApplicationWindowPtr const& rhs) |
1072 | +{ |
1073 | + return !(lhs == rhs); |
1074 | +} |
1075 | |
1076 | // This method is needed to create an unresolved external for the |
1077 | // WindowManager::Default method. This is because it is highly likely that |
1078 | |
1079 | === modified file 'unity-shared/ApplicationManager.h' |
1080 | --- unity-shared/ApplicationManager.h 2013-09-11 09:11:30 +0000 |
1081 | +++ unity-shared/ApplicationManager.h 2015-05-22 16:04:25 +0000 |
1082 | @@ -50,13 +50,35 @@ |
1083 | LEAVE |
1084 | }; |
1085 | |
1086 | +enum class AppType |
1087 | +{ |
1088 | + NORMAL, |
1089 | + WEBAPP, |
1090 | + MOCK, |
1091 | + UNKNOWN |
1092 | +}; |
1093 | + |
1094 | +enum class WindowType |
1095 | +{ |
1096 | + NORMAL, |
1097 | + DESKTOP, |
1098 | + DOCK, |
1099 | + DIALOG, |
1100 | + TOOLBAR, |
1101 | + MENU, |
1102 | + UTILITY, |
1103 | + SPLASHSCREEN, |
1104 | + TAB, |
1105 | + MOCK, |
1106 | + UNKNOWN |
1107 | +}; |
1108 | + |
1109 | class ApplicationWindow |
1110 | { |
1111 | public: |
1112 | virtual ~ApplicationWindow() = default; |
1113 | |
1114 | - virtual std::string type() const = 0; // 'window' or 'tab' |
1115 | - |
1116 | + virtual WindowType type() const = 0; |
1117 | virtual Window window_id() const = 0; |
1118 | virtual int monitor() const = 0; |
1119 | |
1120 | @@ -69,20 +91,32 @@ |
1121 | // Closes the window, or the browser tab if a webapp. |
1122 | virtual void Quit() const = 0; |
1123 | |
1124 | + virtual bool operator==(ApplicationWindow const& other) const |
1125 | + { |
1126 | + return (window_id() == other.window_id()); |
1127 | + } |
1128 | + |
1129 | + virtual bool operator!=(ApplicationWindow const& other) const |
1130 | + { |
1131 | + return !(operator==(other)); |
1132 | + } |
1133 | + |
1134 | nux::ROProperty<std::string> title; |
1135 | nux::ROProperty<std::string> icon; |
1136 | |
1137 | nux::ROProperty<bool> visible; |
1138 | nux::ROProperty<bool> active; |
1139 | nux::ROProperty<bool> urgent; |
1140 | + nux::ROProperty<bool> maximized; |
1141 | }; |
1142 | |
1143 | + |
1144 | class Application |
1145 | { |
1146 | public: |
1147 | virtual ~Application() = default; |
1148 | |
1149 | - virtual std::string type() const = 0; |
1150 | + virtual AppType type() const = 0; |
1151 | |
1152 | // A string representation of the object. |
1153 | virtual std::string repr() const = 0; |
1154 | @@ -102,6 +136,17 @@ |
1155 | virtual void LogEvent(ApplicationEventType, ApplicationSubjectPtr const&) const = 0; |
1156 | |
1157 | virtual std::string desktop_id() const = 0; |
1158 | + |
1159 | + virtual bool operator==(Application const& other) const |
1160 | + { |
1161 | + return (!desktop_id().empty() && (desktop_id() == other.desktop_id())); |
1162 | + } |
1163 | + |
1164 | + virtual bool operator!=(Application const& other) const |
1165 | + { |
1166 | + return !(operator==(other)); |
1167 | + } |
1168 | + |
1169 | nux::ROProperty<std::string> desktop_file; |
1170 | nux::ROProperty<std::string> title; |
1171 | nux::ROProperty<std::string> icon; |
1172 | @@ -117,11 +162,12 @@ |
1173 | |
1174 | sigc::signal<void> closed; |
1175 | |
1176 | - sigc::signal<void, ApplicationWindow const&> window_opened; |
1177 | - sigc::signal<void, ApplicationWindow const&> window_moved; |
1178 | - sigc::signal<void> window_closed; |
1179 | + sigc::signal<void, ApplicationWindowPtr const&> window_opened; |
1180 | + sigc::signal<void, ApplicationWindowPtr const&> window_moved; |
1181 | + sigc::signal<void, ApplicationWindowPtr const&> window_closed; |
1182 | }; |
1183 | |
1184 | + |
1185 | class ApplicationSubject |
1186 | { |
1187 | public: |
1188 | @@ -165,16 +211,28 @@ |
1189 | static ApplicationManager& Default(); |
1190 | |
1191 | virtual ApplicationPtr GetUnityApplication() const = 0; |
1192 | + virtual ApplicationPtr GetActiveApplication() const = 0; |
1193 | virtual ApplicationWindowPtr GetActiveWindow() const = 0; |
1194 | virtual ApplicationPtr GetApplicationForDesktopFile(std::string const& desktop_file) const = 0; |
1195 | virtual ApplicationList GetRunningApplications() const = 0; |
1196 | + virtual WindowList GetWindowsForMonitor(int monitor = -1) const = 0; |
1197 | virtual ApplicationPtr GetApplicationForWindow(Window xid) const = 0; |
1198 | + virtual ApplicationWindowPtr GetWindowForId(Window xid) const = 0; |
1199 | |
1200 | sigc::signal<void, ApplicationPtr const&> application_started; |
1201 | + sigc::signal<void, ApplicationPtr const&> application_stopped; |
1202 | sigc::signal<void, ApplicationPtr const&> active_application_changed; |
1203 | + sigc::signal<void, ApplicationWindowPtr const&> window_opened; |
1204 | + sigc::signal<void, ApplicationWindowPtr const&> window_closed; |
1205 | sigc::signal<void, ApplicationWindowPtr const&> active_window_changed; |
1206 | }; |
1207 | |
1208 | + |
1209 | +bool operator==(ApplicationPtr const&, ApplicationPtr const&); |
1210 | +bool operator!=(ApplicationPtr const&, ApplicationPtr const&); |
1211 | +bool operator==(ApplicationWindowPtr const&, ApplicationWindowPtr const&); |
1212 | +bool operator!=(ApplicationWindowPtr const&, ApplicationWindowPtr const&); |
1213 | + |
1214 | } |
1215 | |
1216 | #endif // UNITYSHARED_APPLICATION_MANAGER_H |
1217 | |
1218 | === modified file 'unity-shared/BamfApplicationManager.cpp' |
1219 | --- unity-shared/BamfApplicationManager.cpp 2013-10-03 22:39:01 +0000 |
1220 | +++ unity-shared/BamfApplicationManager.cpp 2015-05-22 16:04:25 +0000 |
1221 | @@ -34,7 +34,47 @@ |
1222 | namespace |
1223 | { |
1224 | const char* UNSEEN_QUARK = "unity-unseen"; |
1225 | -} |
1226 | + |
1227 | +namespace pool |
1228 | +{ |
1229 | +// We keep a cache on views here, it would be nice to clean these on BAMF reload |
1230 | +std::unordered_map<BamfView*, ApplicationPtr> apps_; |
1231 | +std::unordered_map<BamfView*, ApplicationWindowPtr> wins_; |
1232 | + |
1233 | +ApplicationPtr EnsureApplication(ApplicationManager const& manager, BamfView* view) |
1234 | +{ |
1235 | + if (!BAMF_IS_APPLICATION(view)) |
1236 | + return nullptr; |
1237 | + |
1238 | + auto it = apps_.find(view); |
1239 | + |
1240 | + if (it != apps_.end()) |
1241 | + return it->second; |
1242 | + |
1243 | + glib::Object<BamfApplication> bamfapp(reinterpret_cast<BamfApplication*>(view), glib::AddRef()); |
1244 | + auto const& app = std::make_shared<Application>(manager, bamfapp); |
1245 | + apps_.insert({view, app}); |
1246 | + return app; |
1247 | +} |
1248 | + |
1249 | +ApplicationWindowPtr EnsureWindow(ApplicationManager const& manager, BamfView* view) |
1250 | +{ |
1251 | + if (!BAMF_IS_WINDOW(view)) |
1252 | + return nullptr; |
1253 | + |
1254 | + auto it = wins_.find(view); |
1255 | + |
1256 | + if (it != wins_.end()) |
1257 | + return it->second; |
1258 | + |
1259 | + glib::Object<BamfWindow> bamfwin(reinterpret_cast<BamfWindow*>(view), glib::AddRef()); |
1260 | + auto const& win = std::make_shared<AppWindow>(manager, bamfwin); |
1261 | + wins_.insert({view, win}); |
1262 | + return win; |
1263 | +} |
1264 | + |
1265 | +} // pool namespace |
1266 | +} // anonymous namespace |
1267 | |
1268 | |
1269 | // Due to the way glib handles object inheritance, we need to cast between pointer types. |
1270 | @@ -54,11 +94,6 @@ |
1271 | return glib::String(bamf_view_get_icon(bamf_view_)).Str(); |
1272 | } |
1273 | |
1274 | -std::string View::type() const |
1275 | -{ |
1276 | - return glib::gchar_to_string(bamf_view_get_view_type(bamf_view_)); |
1277 | -} |
1278 | - |
1279 | bool View::GetVisible() const |
1280 | { |
1281 | return bamf_view_is_user_visible(bamf_view_); |
1282 | @@ -80,11 +115,6 @@ |
1283 | } |
1284 | |
1285 | |
1286 | -std::string WindowBase::type() const |
1287 | -{ |
1288 | - return View::type(); |
1289 | -} |
1290 | - |
1291 | WindowBase::WindowBase(ApplicationManager const& manager, |
1292 | glib::Object<BamfView> const& window) |
1293 | : View(manager, window) |
1294 | @@ -122,13 +152,10 @@ |
1295 | Window xid = window_id(); |
1296 | if (xid) |
1297 | { |
1298 | - std::vector<Window> windows = { xid }; |
1299 | - // TODO: we should simplify the use case of focusing one window. |
1300 | - // Somewhat outside the scope of these changes however. |
1301 | - WindowManager::Default().FocusWindowGroup( |
1302 | - windows, |
1303 | - WindowManager::FocusVisibility::ForceUnminimizeInvisible, |
1304 | - monitor(),true); |
1305 | + auto& wm = WindowManager::Default(); |
1306 | + wm.UnMinimize(xid); |
1307 | + wm.Raise(xid); |
1308 | + wm.Activate(xid); |
1309 | return true; |
1310 | } |
1311 | return false; |
1312 | @@ -136,14 +163,25 @@ |
1313 | |
1314 | |
1315 | AppWindow::AppWindow(ApplicationManager const& manager, glib::Object<BamfWindow> const& window) |
1316 | - : WindowBase(manager, glib::object_cast<BamfView>(window)) |
1317 | - , bamf_window_(window) |
1318 | + : AppWindow(manager, glib::object_cast<BamfView>(window)) |
1319 | {} |
1320 | |
1321 | AppWindow::AppWindow(ApplicationManager const& manager, glib::Object<BamfView> const& window) |
1322 | : WindowBase(manager, window) |
1323 | , bamf_window_(glib::object_cast<BamfWindow>(window)) |
1324 | -{} |
1325 | +{ |
1326 | + maximized.SetGetterFunction(std::bind(&AppWindow::GetMaximized, this)); |
1327 | + signals_.Add<void, BamfWindow*, gint, gint>(bamf_window_, "maximized-changed", |
1328 | + [this] (BamfWindow*, gint old_state, gint state) { |
1329 | + if ((old_state == BAMF_WINDOW_MAXIMIZED) != (state == BAMF_WINDOW_MAXIMIZED)) |
1330 | + this->maximized.changed.emit(state == BAMF_WINDOW_MAXIMIZED); |
1331 | + }); |
1332 | +} |
1333 | + |
1334 | +bool AppWindow::GetMaximized() const |
1335 | +{ |
1336 | + return bamf_window_maximized(bamf_window_) == BAMF_WINDOW_MAXIMIZED; |
1337 | +} |
1338 | |
1339 | Window AppWindow::window_id() const |
1340 | { |
1341 | @@ -155,6 +193,31 @@ |
1342 | return bamf_window_get_monitor(bamf_window_); |
1343 | } |
1344 | |
1345 | +WindowType AppWindow::type() const |
1346 | +{ |
1347 | + switch (bamf_window_get_window_type(bamf_window_)) |
1348 | + { |
1349 | + case BAMF_WINDOW_NORMAL: |
1350 | + return WindowType::NORMAL; |
1351 | + case BAMF_WINDOW_DESKTOP: |
1352 | + return WindowType::DESKTOP; |
1353 | + case BAMF_WINDOW_DOCK: |
1354 | + return WindowType::DOCK; |
1355 | + case BAMF_WINDOW_DIALOG: |
1356 | + return WindowType::DIALOG; |
1357 | + case BAMF_WINDOW_TOOLBAR: |
1358 | + return WindowType::TOOLBAR; |
1359 | + case BAMF_WINDOW_MENU: |
1360 | + return WindowType::MENU; |
1361 | + case BAMF_WINDOW_UTILITY: |
1362 | + return WindowType::UTILITY; |
1363 | + case BAMF_WINDOW_SPLASHSCREEN: |
1364 | + return WindowType::SPLASHSCREEN; |
1365 | + default: |
1366 | + return WindowType::UNKNOWN; |
1367 | + } |
1368 | +} |
1369 | + |
1370 | ApplicationPtr AppWindow::application() const |
1371 | { |
1372 | // Moderately evil, but better than changing the method to non-const. |
1373 | @@ -183,6 +246,11 @@ |
1374 | return bamf_tab_get_xid(bamf_tab_); |
1375 | } |
1376 | |
1377 | +WindowType Tab::type() const |
1378 | +{ |
1379 | + return WindowType::TAB; |
1380 | +} |
1381 | + |
1382 | int Tab::monitor() const |
1383 | { |
1384 | // TODO, we could find the real window for the window_id, and get the monitor for that. |
1385 | @@ -208,37 +276,14 @@ |
1386 | bamf_tab_close(bamf_tab_); |
1387 | } |
1388 | |
1389 | -// Being brutal with this function. |
1390 | -ApplicationWindowPtr create_window(ApplicationManager const& manager, glib::Object<BamfView> const& view) |
1391 | -{ |
1392 | - if (view.IsType(BAMF_TYPE_WINDOW)) |
1393 | - { |
1394 | - return std::make_shared<AppWindow>(manager, view); |
1395 | - } |
1396 | - else if (view.IsType(BAMF_TYPE_TAB)) |
1397 | - { |
1398 | - return std::make_shared<Tab>(manager, view); |
1399 | - } |
1400 | - // We don't handle applications here. |
1401 | - return nullptr; |
1402 | -} |
1403 | - |
1404 | Application::Application(ApplicationManager const& manager, glib::Object<BamfView> const& app) |
1405 | - : View(manager, app) |
1406 | - , bamf_app_(glib::object_cast<BamfApplication>(app)) |
1407 | -{ |
1408 | - HookUpEvents(); |
1409 | -} |
1410 | + : Application(manager, glib::object_cast<BamfApplication>(app)) |
1411 | +{} |
1412 | |
1413 | Application::Application(ApplicationManager const& manager, glib::Object<BamfApplication> const& app) |
1414 | : View(manager, glib::object_cast<BamfView>(app)) |
1415 | , bamf_app_(app) |
1416 | { |
1417 | - HookUpEvents(); |
1418 | -} |
1419 | - |
1420 | -void Application::HookUpEvents() |
1421 | -{ |
1422 | // Hook up the property set/get functions |
1423 | using namespace std::placeholders; |
1424 | desktop_file.SetGetterFunction(std::bind(&Application::GetDesktopFile, this)); |
1425 | @@ -292,24 +337,21 @@ |
1426 | signals_.Add<void, BamfView*, BamfView*>(bamf_view_, "child-added", |
1427 | [this] (BamfView*, BamfView* child) { |
1428 | // Ownership is not passed on signals |
1429 | - glib::Object<BamfView> view(child, glib::AddRef()); |
1430 | - ApplicationWindowPtr const& win = create_window(this->manager_, view); |
1431 | - if (win) |
1432 | - this->window_opened.emit(*win); |
1433 | + if (ApplicationWindowPtr const& win = pool::EnsureWindow(manager_, child)) |
1434 | + this->window_opened.emit(win); |
1435 | }); |
1436 | |
1437 | signals_.Add<void, BamfView*, BamfView*>(bamf_view_, "child-removed", |
1438 | [this] (BamfView*, BamfView* child) { |
1439 | - this->window_closed.emit(); |
1440 | + if (ApplicationWindowPtr const& win = pool::EnsureWindow(manager_, child)) |
1441 | + this->window_closed.emit(win); |
1442 | }); |
1443 | |
1444 | signals_.Add<void, BamfView*, BamfView*>(bamf_view_, "child-moved", |
1445 | [this] (BamfView*, BamfView* child) { |
1446 | // Ownership is not passed on signals |
1447 | - glib::Object<BamfView> view(child, glib::AddRef()); |
1448 | - ApplicationWindowPtr const& win = create_window(this->manager_, view); |
1449 | - if (win) |
1450 | - this->window_moved.emit(*win); |
1451 | + if (ApplicationWindowPtr const& win = pool::EnsureWindow(manager_, child)) |
1452 | + this->window_moved.emit(win); |
1453 | }); |
1454 | } |
1455 | |
1456 | @@ -318,16 +360,21 @@ |
1457 | return glib::gchar_to_string(bamf_application_get_desktop_file(bamf_app_)); |
1458 | } |
1459 | |
1460 | -std::string Application::type() const |
1461 | +AppType Application::type() const |
1462 | { |
1463 | // Can't determine the type of a non-running app. |
1464 | - std::string result = "unknown"; |
1465 | if (running()) |
1466 | { |
1467 | - const gchar* type = bamf_application_get_application_type(bamf_app_); |
1468 | - if (type) result = type; |
1469 | + auto type = glib::gchar_to_string(bamf_application_get_application_type(bamf_app_)); |
1470 | + |
1471 | + if (type == "system") |
1472 | + return AppType::NORMAL; |
1473 | + |
1474 | + if (type == "webapp") |
1475 | + return AppType::WEBAPP; |
1476 | } |
1477 | - return result; |
1478 | + |
1479 | + return AppType::UNKNOWN; |
1480 | } |
1481 | |
1482 | std::string Application::repr() const |
1483 | @@ -347,9 +394,7 @@ |
1484 | std::shared_ptr<GList> children(bamf_view_get_children(bamf_view_), g_list_free); |
1485 | for (GList* l = children.get(); l; l = l->next) |
1486 | { |
1487 | - glib::Object<BamfView> view(BAMF_VIEW(l->data), glib::AddRef()); |
1488 | - ApplicationWindowPtr const& window(create_window(manager_, view)); |
1489 | - if (window) |
1490 | + if (ApplicationWindowPtr const& window = pool::EnsureWindow(manager_, static_cast<BamfView*>(l->data))) |
1491 | result.push_back(window); |
1492 | } |
1493 | return result; |
1494 | @@ -389,9 +434,7 @@ |
1495 | |
1496 | ApplicationWindowPtr Application::GetFocusableWindow() const |
1497 | { |
1498 | - glib::Object<BamfView> view(bamf_application_get_focusable_child(bamf_app_), |
1499 | - glib::AddRef()); |
1500 | - return create_window(manager_, view); |
1501 | + return pool::EnsureWindow(manager_, bamf_application_get_focusable_child(bamf_app_)); |
1502 | } |
1503 | |
1504 | void Application::Focus(bool show_only_visible, int monitor) const |
1505 | @@ -507,29 +550,19 @@ |
1506 | LOG_TRACE(logger) << "Create BAMF Application Manager"; |
1507 | signals_.Add<void, BamfMatcher*, BamfView*> (matcher_, "view-opened", |
1508 | sigc::mem_fun(this, &Manager::OnViewOpened)); |
1509 | + signals_.Add<void, BamfMatcher*, BamfView*> (matcher_, "view-closed", |
1510 | + sigc::mem_fun(this, &Manager::OnViewClosed)); |
1511 | |
1512 | signals_.Add<void, BamfMatcher*, BamfView*, BamfView*>(matcher_, "active-window-changed", |
1513 | [this](BamfMatcher*, BamfView* /* from */, BamfView* to) { |
1514 | - // Ownership is not passed on signals |
1515 | - glib::Object<BamfView> view(to, glib::AddRef()); |
1516 | - ApplicationWindowPtr const& win = create_window(*this, view); |
1517 | - if (win) |
1518 | + if (ApplicationWindowPtr const& win = pool::EnsureWindow(*this, to)) |
1519 | this->active_window_changed.emit(win); |
1520 | }); |
1521 | |
1522 | signals_.Add<void, BamfMatcher*, BamfApplication*, BamfApplication*> (matcher_, "active-application-changed", |
1523 | [this](BamfMatcher*, BamfApplication* /* from */, BamfApplication* to) { |
1524 | - if (to) |
1525 | - { |
1526 | - // Ownership is not passed on signals |
1527 | - glib::Object<BamfApplication> bamf_app(to, glib::AddRef()); |
1528 | - auto app = std::make_shared<Application>(*this, bamf_app); |
1529 | - this->active_application_changed.emit(app); |
1530 | - } |
1531 | - else |
1532 | - { |
1533 | - this->active_application_changed.emit(nullptr); |
1534 | - } |
1535 | + auto const& app = pool::EnsureApplication(*this, reinterpret_cast<BamfView*>(to)); |
1536 | + this->active_application_changed.emit(app); |
1537 | }); |
1538 | } |
1539 | |
1540 | @@ -546,81 +579,79 @@ |
1541 | { |
1542 | auto *app_ptr = bamf_matcher_get_application_for_xid(matcher_, xid); |
1543 | |
1544 | - if (BAMF_IS_APPLICATION(app_ptr)) |
1545 | - { |
1546 | - glib::Object<BamfApplication> app(app_ptr, glib::AddRef()); |
1547 | - return std::make_shared<Application>(*this, app); |
1548 | - } |
1549 | + if (ApplicationPtr const& app = pool::EnsureApplication(*this, reinterpret_cast<BamfView*>(app_ptr))) |
1550 | + return app; |
1551 | } |
1552 | |
1553 | return GetApplicationForDesktopFile(DesktopUtilities::GetDesktopPathById("compiz.desktop")); |
1554 | } |
1555 | |
1556 | +ApplicationPtr Manager::GetActiveApplication() const |
1557 | +{ |
1558 | + auto *app_ptr = bamf_matcher_get_active_application(matcher_); |
1559 | + return pool::EnsureApplication(*this, reinterpret_cast<BamfView*>(app_ptr)); |
1560 | +} |
1561 | + |
1562 | ApplicationWindowPtr Manager::GetActiveWindow() const |
1563 | { |
1564 | - // No transfer of ownership for bamf_matcher_get_active_window. |
1565 | - BamfWindow* active_win = bamf_matcher_get_active_window(matcher_); |
1566 | - |
1567 | - if (!active_win) |
1568 | - return nullptr; |
1569 | + if (BamfWindow* active_win = bamf_matcher_get_active_window(matcher_)) |
1570 | + { |
1571 | + if (bamf_window_get_window_type(active_win) != BAMF_WINDOW_DOCK) |
1572 | + return pool::EnsureWindow(*this, reinterpret_cast<BamfView*>(active_win)); |
1573 | + } |
1574 | |
1575 | // If the active window is a dock type, then we want the first visible, non-dock type. |
1576 | - if (bamf_window_get_window_type(active_win) == BAMF_WINDOW_DOCK) |
1577 | + LOG_DEBUG(logger) << "Is a dock, looking at the window stack."; |
1578 | + |
1579 | + auto const& wins = GetWindowsForMonitor(); |
1580 | + WindowManager& wm = WindowManager::Default(); |
1581 | + |
1582 | + for (auto it = wins.rbegin(); it != wins.rend(); ++it) |
1583 | { |
1584 | - LOG_DEBUG(logger) << "Is a dock, looking at the window stack."; |
1585 | - |
1586 | - std::shared_ptr<GList> windows(bamf_matcher_get_window_stack_for_monitor(matcher_, -1), g_list_free); |
1587 | - WindowManager& wm = WindowManager::Default(); |
1588 | - active_win = nullptr; |
1589 | - |
1590 | - for (GList *l = windows.get(); l; l = l->next) |
1591 | + auto const& win = *it; |
1592 | + auto xid = win->window_id(); |
1593 | + |
1594 | + if (win->visible() && |
1595 | + win->type() != WindowType::DOCK && |
1596 | + wm.IsWindowOnCurrentDesktop(xid) && |
1597 | + wm.IsWindowVisible(xid)) |
1598 | { |
1599 | - if (!BAMF_IS_WINDOW(l->data)) |
1600 | - { |
1601 | - LOG_DEBUG(logger) << "Window stack returned something not a window, WTF?"; |
1602 | - continue; |
1603 | - } |
1604 | - |
1605 | - auto win = static_cast<BamfWindow*>(l->data); |
1606 | - auto view = static_cast<BamfView*>(l->data); |
1607 | - auto xid = bamf_window_get_xid(win); |
1608 | - |
1609 | - if (bamf_view_is_user_visible(view) && |
1610 | - bamf_window_get_window_type(win) != BAMF_WINDOW_DOCK && |
1611 | - wm.IsWindowOnCurrentDesktop(xid) && |
1612 | - wm.IsWindowVisible(xid)) |
1613 | - { |
1614 | - active_win = win; |
1615 | - } |
1616 | + return win; |
1617 | } |
1618 | } |
1619 | |
1620 | - if (active_win) |
1621 | - { |
1622 | - glib::Object<BamfWindow> win(active_win, glib::AddRef()); |
1623 | - return std::make_shared<AppWindow>(*this, win); |
1624 | - } |
1625 | - |
1626 | return nullptr; |
1627 | } |
1628 | |
1629 | ApplicationPtr Manager::GetApplicationForDesktopFile(std::string const& desktop_file) const |
1630 | { |
1631 | - glib::Object<BamfApplication> app(bamf_matcher_get_application_for_desktop_file( |
1632 | - matcher_, desktop_file.c_str(), TRUE), glib::AddRef()); |
1633 | - |
1634 | - if (app) |
1635 | - return std::make_shared<Application>(*this, app); |
1636 | - |
1637 | - return nullptr; |
1638 | + auto* app = bamf_matcher_get_application_for_desktop_file(matcher_, desktop_file.c_str(), TRUE); |
1639 | + return pool::EnsureApplication(*this, reinterpret_cast<BamfView*>(app)); |
1640 | } |
1641 | |
1642 | ApplicationPtr Manager::GetApplicationForWindow(Window xid) const |
1643 | { |
1644 | - glib::Object<BamfApplication> app(bamf_matcher_get_application_for_xid(matcher_, xid), |
1645 | - glib::AddRef()); |
1646 | - if (app) |
1647 | - return std::make_shared<Application>(*this, app); |
1648 | + auto* app = bamf_matcher_get_application_for_xid(matcher_, xid); |
1649 | + return pool::EnsureApplication(*this, reinterpret_cast<BamfView*>(app)); |
1650 | +} |
1651 | + |
1652 | +ApplicationWindowPtr Manager::GetWindowForId(Window xid) const |
1653 | +{ |
1654 | + if (xid == 0) |
1655 | + return nullptr; |
1656 | + |
1657 | + std::shared_ptr<GList> windows(bamf_matcher_get_windows(matcher_), g_list_free); |
1658 | + |
1659 | + for (GList* l = windows.get(); l; l = l->next) |
1660 | + { |
1661 | + if (!BAMF_IS_WINDOW(l->data)) |
1662 | + continue; |
1663 | + |
1664 | + auto win = static_cast<BamfWindow*>(l->data); |
1665 | + |
1666 | + if (bamf_window_get_xid(win) == xid) |
1667 | + return pool::EnsureWindow(*this, static_cast<BamfView*>(l->data)); |
1668 | + } |
1669 | |
1670 | return nullptr; |
1671 | } |
1672 | @@ -638,26 +669,65 @@ |
1673 | continue; |
1674 | } |
1675 | |
1676 | - glib::Object<BamfApplication> bamf_app(static_cast<BamfApplication*>(l->data), glib::AddRef()); |
1677 | - auto app = std::make_shared<Application>(*this, bamf_app); |
1678 | - result.push_back(app); |
1679 | - LOG_DEBUG(logger) << "Running app: " << app->title(); |
1680 | + result.push_back(pool::EnsureApplication(*this, static_cast<BamfView*>(l->data))); |
1681 | } |
1682 | return result; |
1683 | } |
1684 | |
1685 | +WindowList Manager::GetWindowsForMonitor(int monitor) const |
1686 | +{ |
1687 | + WindowList wins; |
1688 | + std::shared_ptr<GList> windows(bamf_matcher_get_window_stack_for_monitor(matcher_, monitor), g_list_free); |
1689 | + |
1690 | + for (GList *l = windows.get(); l; l = l->next) |
1691 | + { |
1692 | + if (!BAMF_IS_WINDOW(l->data)) |
1693 | + { |
1694 | + LOG_DEBUG(logger) << "Window stack returned something not a window, WTF?"; |
1695 | + continue; |
1696 | + } |
1697 | + |
1698 | + auto bamf_win = static_cast<BamfWindow*>(l->data); |
1699 | + |
1700 | + if (bamf_window_get_window_type(bamf_win) != BAMF_WINDOW_DOCK) |
1701 | + wins.push_back(pool::EnsureWindow(*this, static_cast<BamfView*>(l->data))); |
1702 | + } |
1703 | + |
1704 | + return wins; |
1705 | +} |
1706 | |
1707 | void Manager::OnViewOpened(BamfMatcher* matcher, BamfView* view) |
1708 | { |
1709 | LOG_TRACE_BLOCK(logger); |
1710 | - if (!BAMF_IS_APPLICATION(view)) |
1711 | - { |
1712 | - LOG_DEBUG(logger) << "view is not an app"; |
1713 | - return; |
1714 | - } |
1715 | - |
1716 | - glib::Object<BamfView> app(view, glib::AddRef()); |
1717 | - application_started.emit(std::make_shared<Application>(*this, app)); |
1718 | + if (BAMF_IS_APPLICATION(view)) |
1719 | + { |
1720 | + if (ApplicationPtr const& app = pool::EnsureApplication(*this, view)) |
1721 | + application_started.emit(app); |
1722 | + } |
1723 | + else if (BAMF_IS_WINDOW(view)) |
1724 | + { |
1725 | + if (ApplicationWindowPtr const& win = pool::EnsureWindow(*this, view)) |
1726 | + window_opened.emit(win); |
1727 | + } |
1728 | +} |
1729 | + |
1730 | +void Manager::OnViewClosed(BamfMatcher* matcher, BamfView* view) |
1731 | +{ |
1732 | + LOG_TRACE_BLOCK(logger); |
1733 | + if (BAMF_IS_APPLICATION(view)) |
1734 | + { |
1735 | + if (ApplicationPtr const& app = pool::EnsureApplication(*this, view)) |
1736 | + application_stopped.emit(app); |
1737 | + |
1738 | + pool::apps_.erase(view); |
1739 | + } |
1740 | + else if (BAMF_IS_WINDOW(view)) |
1741 | + { |
1742 | + if (ApplicationWindowPtr const& win = pool::EnsureWindow(*this, view)) |
1743 | + window_closed.emit(win); |
1744 | + |
1745 | + pool::wins_.erase(view); |
1746 | + } |
1747 | } |
1748 | |
1749 | } // namespace bamf |
1750 | |
1751 | === modified file 'unity-shared/BamfApplicationManager.h' |
1752 | --- unity-shared/BamfApplicationManager.h 2013-09-04 19:38:19 +0000 |
1753 | +++ unity-shared/BamfApplicationManager.h 2015-05-22 16:04:25 +0000 |
1754 | @@ -20,6 +20,7 @@ |
1755 | #ifndef UNITYSHARED_BAMF_APPLICATION_MANAGER_H |
1756 | #define UNITYSHARED_BAMF_APPLICATION_MANAGER_H |
1757 | |
1758 | +#include <unordered_map> |
1759 | #include <libbamf/libbamf.h> |
1760 | #include <UnityCore/GLibWrapper.h> |
1761 | #include <UnityCore/GLibSignal.h> |
1762 | @@ -39,7 +40,6 @@ |
1763 | |
1764 | std::string GetTitle() const; |
1765 | std::string GetIcon() const; |
1766 | - std::string type() const; |
1767 | |
1768 | bool GetVisible() const; |
1769 | bool GetActive() const; |
1770 | @@ -59,11 +59,15 @@ |
1771 | glib::Object<BamfView> const& window); |
1772 | |
1773 | public: |
1774 | - virtual std::string type() const; // 'window' or 'tab' |
1775 | - |
1776 | - virtual bool Focus() const; |
1777 | - |
1778 | -private: |
1779 | + bool Focus() const override; |
1780 | + |
1781 | + bool operator==(unity::ApplicationWindow const& other) const override |
1782 | + { |
1783 | + return static_cast<WindowBase const*>(this)->bamf_view_ == static_cast<WindowBase const&>(other).bamf_view_; |
1784 | + } |
1785 | + bool operator!=(unity::ApplicationWindow const& other) const override { return !(operator==(other)); } |
1786 | + |
1787 | +protected: |
1788 | glib::SignalManager signals_; |
1789 | }; |
1790 | |
1791 | @@ -76,10 +80,12 @@ |
1792 | AppWindow(ApplicationManager const& manager, |
1793 | glib::Object<BamfView> const& window); |
1794 | |
1795 | - virtual Window window_id() const; |
1796 | - virtual int monitor() const; |
1797 | - virtual ApplicationPtr application() const; |
1798 | - virtual void Quit() const; |
1799 | + WindowType type() const override; |
1800 | + Window window_id() const override; |
1801 | + int monitor() const override; |
1802 | + ApplicationPtr application() const override; |
1803 | + void Quit() const override; |
1804 | + bool GetMaximized() const; |
1805 | |
1806 | private: |
1807 | glib::Object<BamfWindow> bamf_window_; |
1808 | @@ -93,11 +99,12 @@ |
1809 | Tab(ApplicationManager const& manager, |
1810 | glib::Object<BamfView> const& tab); |
1811 | |
1812 | - virtual Window window_id() const; |
1813 | - virtual int monitor() const; |
1814 | - virtual ApplicationPtr application() const; |
1815 | - virtual bool Focus() const; |
1816 | - virtual void Quit() const; |
1817 | + WindowType type() const override; |
1818 | + Window window_id() const override; |
1819 | + int monitor() const override; |
1820 | + ApplicationPtr application() const override; |
1821 | + bool Focus() const override; |
1822 | + void Quit() const override; |
1823 | |
1824 | private: |
1825 | glib::Object<BamfTab> bamf_tab_; |
1826 | @@ -112,7 +119,7 @@ |
1827 | Application(ApplicationManager const& manager, |
1828 | glib::Object<BamfView> const& app); |
1829 | |
1830 | - virtual std::string type() const; |
1831 | + virtual AppType type() const; |
1832 | |
1833 | virtual WindowList GetWindows() const; |
1834 | virtual bool OwnsWindow(Window window_id) const; |
1835 | @@ -128,9 +135,13 @@ |
1836 | |
1837 | virtual std::string repr() const; |
1838 | |
1839 | + bool operator==(unity::Application const& other) const override |
1840 | + { |
1841 | + return static_cast<Application const*>(this)->bamf_app_ == static_cast<Application const&>(other).bamf_app_; |
1842 | + } |
1843 | + bool operator!=(unity::Application const& other) const override { return !(operator==(other)); } |
1844 | + |
1845 | private: // Property getters and setters |
1846 | - void HookUpEvents(); |
1847 | - |
1848 | std::string GetDesktopFile() const; |
1849 | |
1850 | bool GetSeen() const; |
1851 | @@ -152,13 +163,20 @@ |
1852 | ~Manager(); |
1853 | |
1854 | ApplicationPtr GetUnityApplication() const override; |
1855 | + ApplicationPtr GetActiveApplication() const override; |
1856 | ApplicationWindowPtr GetActiveWindow() const override; |
1857 | ApplicationPtr GetApplicationForDesktopFile(std::string const& desktop_file) const override; |
1858 | ApplicationList GetRunningApplications() const override; |
1859 | + WindowList GetWindowsForMonitor(int monitor = -1) const override; |
1860 | ApplicationPtr GetApplicationForWindow(Window xid) const override; |
1861 | + ApplicationWindowPtr GetWindowForId(Window xid) const override; |
1862 | + |
1863 | + ApplicationPtr EnsureApplication(BamfView*) const; |
1864 | + ApplicationWindowPtr EnsureWindow(BamfView*) const; |
1865 | |
1866 | private: |
1867 | void OnViewOpened(BamfMatcher* matcher, BamfView* view); |
1868 | + void OnViewClosed(BamfMatcher* matcher, BamfView* view); |
1869 | |
1870 | private: |
1871 | glib::Object<BamfMatcher> matcher_; |
1872 | |
1873 | === modified file 'unity-shared/StandaloneAppManager.cpp' |
1874 | --- unity-shared/StandaloneAppManager.cpp 2014-07-30 00:49:35 +0000 |
1875 | +++ unity-shared/StandaloneAppManager.cpp 2015-05-22 16:04:25 +0000 |
1876 | @@ -33,6 +33,54 @@ |
1877 | |
1878 | GMainLoop *loop; |
1879 | |
1880 | +std::ostream& operator<<(std::ostream &os, AppType at) |
1881 | +{ |
1882 | + switch (at) |
1883 | + { |
1884 | + case AppType::NORMAL: |
1885 | + return os << "NORMAL"; |
1886 | + case AppType::WEBAPP: |
1887 | + return os << "WEBAPP"; |
1888 | + case AppType::MOCK: |
1889 | + return os << "MOCK"; |
1890 | + case AppType::UNKNOWN: |
1891 | + return os << "UNKNOWN"; |
1892 | + } |
1893 | + |
1894 | + return os; |
1895 | +} |
1896 | + |
1897 | +std::ostream& operator<<(std::ostream &os, WindowType wt) |
1898 | +{ |
1899 | + switch (wt) |
1900 | + { |
1901 | + case WindowType::NORMAL: |
1902 | + return os << "NORMAL"; |
1903 | + case WindowType::DESKTOP: |
1904 | + return os << "DESKTOP"; |
1905 | + case WindowType::DOCK: |
1906 | + return os << "DOCK"; |
1907 | + case WindowType::DIALOG: |
1908 | + return os << "DIALOG"; |
1909 | + case WindowType::TOOLBAR: |
1910 | + return os << "TOOLBAR"; |
1911 | + case WindowType::MENU: |
1912 | + return os << "MENU"; |
1913 | + case WindowType::UTILITY: |
1914 | + return os << "UTILITY"; |
1915 | + case WindowType::SPLASHSCREEN: |
1916 | + return os << "SPLASHSCREEN"; |
1917 | + case WindowType::TAB: |
1918 | + return os << "TAB"; |
1919 | + case WindowType::MOCK: |
1920 | + return os << "MOCK"; |
1921 | + case WindowType::UNKNOWN: |
1922 | + return os << "UNKNOWN"; |
1923 | + } |
1924 | + |
1925 | + return os; |
1926 | +} |
1927 | + |
1928 | void dump_app(ApplicationPtr const& app, std::string const& prefix = "") |
1929 | { |
1930 | if (app) |
1931 | @@ -55,6 +103,7 @@ |
1932 | std::cout << " Window: " << win->title() |
1933 | << ", window_id: " << win->window_id() |
1934 | << ", monitor: " << win->monitor() |
1935 | + << ", maximized: " << win->maximized() |
1936 | << ", type: " << win->type() |
1937 | << endl; |
1938 | } |
1939 | @@ -65,6 +114,8 @@ |
1940 | } |
1941 | } |
1942 | |
1943 | +std::vector<std::string> names; |
1944 | + |
1945 | void connect_events(ApplicationPtr const& app) |
1946 | { |
1947 | if (app->seen()) |
1948 | @@ -72,42 +123,57 @@ |
1949 | cout << "Already seen " << app->title() << ", skipping event connection.\n"; |
1950 | return; |
1951 | } |
1952 | - std::string app_name = app->title(); |
1953 | - app->title.changed.connect([&app_name](std::string const& value) { |
1954 | - cout << app_name << " changed name to: " << value << endl; |
1955 | - app_name = value; |
1956 | - }); |
1957 | - app->icon.changed.connect([&app_name](std::string const& value) { |
1958 | - cout << app_name << " icon changed: " << value << endl; |
1959 | - }); |
1960 | - app->desktop_file.changed.connect([&app_name](std::string const& value) { |
1961 | - cout << app_name << " desktop file changed: " << value << endl; |
1962 | - }); |
1963 | - app->visible.changed.connect([&app_name](bool value) { |
1964 | - cout << app_name << " visibility changed: " << (value ? "yes" : "no") << endl; |
1965 | - }); |
1966 | - app->running.changed.connect([&app_name](bool value) { |
1967 | - cout << app_name << " running changed: " << (value ? "yes" : "no") << endl; |
1968 | - }); |
1969 | - app->active.changed.connect([&app_name](bool value) { |
1970 | - cout << app_name << " active changed: " << (value ? "yes" : "no") << endl; |
1971 | - }); |
1972 | - app->urgent.changed.connect([&app_name](bool value) { |
1973 | - cout << app_name << " urgent changed: " << (value ? "yes" : "no") << endl; |
1974 | - }); |
1975 | - app->closed.connect([&app_name]() { |
1976 | - cout << app_name << " closed." << endl; |
1977 | - }); |
1978 | - app->window_opened.connect([&app_name](ApplicationWindow const& window) { |
1979 | - cout << "** " << app_name << " window opened: " << window.title() << endl; |
1980 | - }); |
1981 | - app->window_closed.connect([&app_name]() { |
1982 | - cout << "** " << app_name << " window closed" << endl; |
1983 | - }); |
1984 | - app->window_moved.connect([&app_name](ApplicationWindow const& window) { |
1985 | - cout << "** " << app_name << " window moved: " << window.title() << endl; |
1986 | + |
1987 | + auto idx = names.empty() ? 0 : names.size()-1; |
1988 | + names.push_back(app->title()); |
1989 | + app->title.changed.connect([idx](std::string const& value) { |
1990 | + cout << names[idx] << " changed name to: " << value << endl; |
1991 | + names[idx] = value; |
1992 | + }); |
1993 | + app->icon.changed.connect([idx](std::string const& value) { |
1994 | + cout << names[idx] << " icon changed: " << value << endl; |
1995 | + }); |
1996 | + app->desktop_file.changed.connect([idx](std::string const& value) { |
1997 | + cout << names[idx] << " desktop file changed: " << value << endl; |
1998 | + }); |
1999 | + app->visible.changed.connect([idx](bool value) { |
2000 | + cout << names[idx] << " visibility changed: " << (value ? "yes" : "no") << endl; |
2001 | + }); |
2002 | + app->running.changed.connect([idx](bool value) { |
2003 | + cout << names[idx] << " running changed: " << (value ? "yes" : "no") << endl; |
2004 | + }); |
2005 | + app->active.changed.connect([idx](bool value) { |
2006 | + cout << names[idx] << " active changed: " << (value ? "yes" : "no") << endl; |
2007 | + }); |
2008 | + app->urgent.changed.connect([idx](bool value) { |
2009 | + cout << names[idx] << " urgent changed: " << (value ? "yes" : "no") << endl; |
2010 | + }); |
2011 | + app->closed.connect([idx]() { |
2012 | + cout << names[idx] << " closed." << endl; |
2013 | + }); |
2014 | + app->window_opened.connect([idx](ApplicationWindowPtr const& window) { |
2015 | + cout << "** " << names[idx] << " window opened: " << window->title() << endl; |
2016 | + }); |
2017 | + app->window_closed.connect([idx](ApplicationWindowPtr const& window) { |
2018 | + cout << "** " << names[idx] << " window closed: " << window->title() << endl; |
2019 | + }); |
2020 | + app->window_moved.connect([idx](ApplicationWindowPtr const& window) { |
2021 | + cout << "** " << names[idx] << " window moved: " << window->title() << endl; |
2022 | }); |
2023 | app->seen = true; |
2024 | + |
2025 | + for (auto win : app->GetWindows()) |
2026 | + { |
2027 | + win->title.changed.connect([win] (std::string const& t) { |
2028 | + std::cout << "Window "<< win->window_id()<< " title changed to "<< t << endl; |
2029 | + }); |
2030 | + win->maximized.changed.connect([win] (bool m) { |
2031 | + std::cout << "Window "<< win->window_id()<< " maximized changed to "<< m << endl; |
2032 | + }); |
2033 | + win->active.changed.connect([win] (bool a) { |
2034 | + std::cout << "Window "<< win->window_id()<< " active changed to "<< a << endl; |
2035 | + }); |
2036 | + } |
2037 | } |
2038 | |
2039 |
FAILED: Continuous integration, rev:3969 jenkins. qa.ubuntu. com/job/ unity-ci/ 1150/ jenkins. qa.ubuntu. com/job/ unity-vivid- amd64-ci/ 37/console jenkins. qa.ubuntu. com/job/ unity-vivid- armhf-ci/ 37/console jenkins. qa.ubuntu. com/job/ unity-vivid- i386-ci/ 37/console
http://
Executed test runs:
FAILURE: http://
FAILURE: http://
FAILURE: http://
Click here to trigger a rebuild: s-jenkins. ubuntu- ci:8080/ job/unity- ci/1150/ rebuild
http://