Merge lp:~alan-griffiths/miral/rework-titlebars into lp:miral
- rework-titlebars
- Merge into trunk
| Status: | Merged |
|---|---|
| Approved by: | Alan Griffiths on 2016-07-08 |
| Approved revision: | 224 |
| Merge reported by: | Alan Griffiths |
| Merged at revision: | not available |
| Proposed branch: | lp:~alan-griffiths/miral/rework-titlebars |
| Merge into: | lp:miral |
| Diff against target: |
1059 lines (+461/-355) 13 files modified
include/miral/window_manager_tools.h (+0/-3) miral-shell/CMakeLists.txt (+4/-4) miral-shell/shell_main.cpp (+1/-1) miral-shell/titlebar/CMakeLists.txt (+0/-13) miral-shell/titlebar/titlebar_user_data.cpp (+0/-171) miral-shell/titlebar/titlebar_user_data.h (+0/-41) miral-shell/titlebar_provider.cpp (+276/-0) miral-shell/titlebar_provider.h (+102/-0) miral-shell/titlebar_window_manager.cpp (+57/-98) miral-shell/titlebar_window_manager.h (+10/-1) miral/application.cpp (+8/-1) miral/basic_window_manager.cpp (+1/-17) miral/basic_window_manager.h (+2/-5) |
| To merge this branch: | bzr merge lp:~alan-griffiths/miral/rework-titlebars |
| Related bugs: |
| Reviewer | Review Type | Date Requested | Status |
|---|---|---|---|
| Alexandros Frantzis (community) | 2016-06-29 | Approve on 2016-07-08 | |
| Alan Griffiths | Abstain on 2016-07-07 | ||
|
Review via email:
|
|||
Commit Message
Re-implement dummy titlebars without using mirserver APIs
Description of the Change
Re-implement dummy titlebars without using mirserver APIs
This completes the separation of miral-shell from libmirserver and allows the removal of the awkward build_window() and destroy() methods from the WindowManagerTools interface.
| Alan Griffiths (alan-griffiths) wrote : | # |
I've found a broken usecase:
Running Xenial + recent build of lp:mir (I should update this and retest).
Run miral-shell on mesa.
Launch all the mir_demo_client_* together.
The titlebars do not get associated correctly with the apps:
1. They all appear grey.
2. The apps can be closed (Alt+F4), but titlebars remain.
3. When all apps can are closed Alt+F4 closes the server. (I guess a titlebar gets focus and the internal client PID is kill(SIGTERM)'d).
| Alan Griffiths (alan-griffiths) wrote : | # |
> I've found a broken usecase:
>
> Running Xenial + recent build of lp:mir (I should update this and retest).
Tested with current lp:mir tip - behaviour is less bad (E.g. there's a bright "focused" titlebar and focus is indicated correctly.)
But, Z-order is wrong as unrelated are sometimes placed between surface and titlebar resulting in the titlebar overlaying a surface above the main window.
And after closing all apps there can be an "orphan" titlebar that gets focus and kills the server on Alt+F4.
- 222. By Alan Griffiths on 2016-07-07
-
Avoid suicide
- 223. By Alan Griffiths on 2016-07-07
-
Don't overspecified function name
- 224. By Alan Griffiths on 2016-07-07
-
Ensure that titlebars are together with main surface in z-order
| Alexandros Frantzis (afrantzis) wrote : | # |
Still looks good (with mir 0.23.1 packages on xenial).
Preview Diff
| 1 | === modified file 'include/miral/window_manager_tools.h' |
| 2 | --- include/miral/window_manager_tools.h 2016-06-17 16:50:29 +0000 |
| 3 | +++ include/miral/window_manager_tools.h 2016-07-07 15:12:19 +0000 |
| 4 | @@ -49,8 +49,6 @@ |
| 5 | * I.e. they should only be used by a thread that has called the WindowManagementPolicy methods |
| 6 | * (where any necessary locks are held) or via a invoke_under_lock() callback. |
| 7 | * @{ */ |
| 8 | - virtual auto build_window(Application const& application, WindowSpecification const& parameters) |
| 9 | - -> WindowInfo& = 0; |
| 10 | virtual auto count_applications() const -> unsigned int = 0; |
| 11 | virtual void for_each_application(std::function<void(ApplicationInfo& info)> const& functor) = 0; |
| 12 | virtual auto find_application(std::function<bool(ApplicationInfo const& info)> const& predicate) |
| 13 | @@ -66,7 +64,6 @@ |
| 14 | virtual void focus_next_within_application() = 0; |
| 15 | virtual auto window_at(mir::geometry::Point cursor) const -> Window = 0; |
| 16 | virtual auto active_display() -> mir::geometry::Rectangle const = 0; |
| 17 | - virtual void destroy(Window& window) = 0; |
| 18 | virtual void raise_tree(Window const& root) = 0; |
| 19 | virtual void modify_window(WindowInfo& window_info, WindowSpecification const& modifications) = 0; |
| 20 | virtual void place_and_size(WindowInfo& window_info, Point const& new_pos, Size const& new_size) = 0; |
| 21 | |
| 22 | === modified file 'miral-shell/CMakeLists.txt' |
| 23 | --- miral-shell/CMakeLists.txt 2016-06-17 16:50:29 +0000 |
| 24 | +++ miral-shell/CMakeLists.txt 2016-07-07 15:12:19 +0000 |
| 25 | @@ -1,6 +1,5 @@ |
| 26 | add_subdirectory(spinner) |
| 27 | add_subdirectory(desktop) |
| 28 | -add_subdirectory(titlebar) |
| 29 | |
| 30 | add_custom_target(miral-run ALL |
| 31 | cp ${CMAKE_CURRENT_SOURCE_DIR}/miral-run.sh ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/miral-run |
| 32 | @@ -12,12 +11,13 @@ |
| 33 | |
| 34 | add_executable(miral-shell |
| 35 | shell_main.cpp |
| 36 | - tiling_window_manager.cpp tiling_window_manager.h |
| 37 | - titlebar_window_manager.cpp titlebar_window_manager.h) |
| 38 | + tiling_window_manager.cpp tiling_window_manager.h |
| 39 | + titlebar_window_manager.cpp titlebar_window_manager.h |
| 40 | + titlebar_provider.cpp titlebar_provider.h |
| 41 | +) |
| 42 | |
| 43 | target_link_libraries(miral-shell |
| 44 | miral-spinner |
| 45 | - miral-titlebar |
| 46 | miral |
| 47 | ) |
| 48 | |
| 49 | |
| 50 | === modified file 'miral-shell/shell_main.cpp' |
| 51 | --- miral-shell/shell_main.cpp 2016-06-17 16:50:29 +0000 |
| 52 | +++ miral-shell/shell_main.cpp 2016-07-07 15:12:19 +0000 |
| 53 | @@ -35,7 +35,7 @@ |
| 54 | InternalClientLauncher launcher; |
| 55 | WindowManagerOptions window_managers |
| 56 | { |
| 57 | - add_window_manager_policy<TitlebarWindowManagerPolicy>("titlebar", spinner), |
| 58 | + add_window_manager_policy<TitlebarWindowManagerPolicy>("titlebar", spinner, launcher), |
| 59 | add_window_manager_policy<CanonicalWindowManagerPolicy>("canonical"), |
| 60 | add_window_manager_policy<TilingWindowManagerPolicy>("tiling", spinner, launcher), |
| 61 | }; |
| 62 | |
| 63 | === removed directory 'miral-shell/titlebar' |
| 64 | === removed file 'miral-shell/titlebar/CMakeLists.txt' |
| 65 | --- miral-shell/titlebar/CMakeLists.txt 2016-06-07 09:24:55 +0000 |
| 66 | +++ miral-shell/titlebar/CMakeLists.txt 1970-01-01 00:00:00 +0000 |
| 67 | @@ -1,13 +0,0 @@ |
| 68 | -# TODO remove dependency on libmirserver-dev |
| 69 | -# (Only needed by awkward painting code) |
| 70 | -pkg_check_modules(MIRSERVER mirserver>=0.20 REQUIRED) |
| 71 | -include_directories(include SYSTEM ${MIRSERVER_INCLUDE_DIRS}) |
| 72 | - |
| 73 | - |
| 74 | -add_library(miral-titlebar STATIC |
| 75 | - titlebar_user_data.cpp titlebar_user_data.h |
| 76 | -) |
| 77 | - |
| 78 | -target_link_libraries(miral-titlebar |
| 79 | - miral |
| 80 | -) |
| 81 | |
| 82 | === removed file 'miral-shell/titlebar/titlebar_user_data.cpp' |
| 83 | --- miral-shell/titlebar/titlebar_user_data.cpp 2016-06-07 19:05:10 +0000 |
| 84 | +++ miral-shell/titlebar/titlebar_user_data.cpp 1970-01-01 00:00:00 +0000 |
| 85 | @@ -1,171 +0,0 @@ |
| 86 | -/* |
| 87 | - * Copyright © 2016 Canonical Ltd. |
| 88 | - * |
| 89 | - * This program is free software: you can redistribute it and/or modify it |
| 90 | - * under the terms of the GNU General Public License version 3, |
| 91 | - * as published by the Free Software Foundation. |
| 92 | - * |
| 93 | - * This program is distributed in the hope that it will be useful, |
| 94 | - * but WITHOUT ANY WARRANTY; without even the implied warranty of |
| 95 | - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
| 96 | - * GNU General Public License for more details. |
| 97 | - * |
| 98 | - * You should have received a copy of the GNU General Public License |
| 99 | - * along with this program. If not, see <http://www.gnu.org/licenses/>. |
| 100 | - * |
| 101 | - * Authored by: Alan Griffiths <alan@octopull.co.uk> |
| 102 | - */ |
| 103 | - |
| 104 | -#include "titlebar_user_data.h" |
| 105 | - |
| 106 | -// TODO We need a better way to support painting stuff inside the window manager |
| 107 | -#include <mir/frontend/buffer_stream.h> |
| 108 | -#include <mir/graphics/buffer.h> |
| 109 | -#include <mir/graphics/buffer_properties.h> |
| 110 | -#include <mir/scene/session.h> |
| 111 | -#include <mir/scene/surface.h> |
| 112 | - |
| 113 | -#include <mir/version.h> |
| 114 | - |
| 115 | -#include <atomic> |
| 116 | - |
| 117 | -using namespace mir::geometry; |
| 118 | - |
| 119 | -struct TitlebarUserData::StreamPainter |
| 120 | -{ |
| 121 | - virtual void paint(int) = 0; |
| 122 | - virtual ~StreamPainter() = default; |
| 123 | - StreamPainter() = default; |
| 124 | - StreamPainter(StreamPainter const&) = delete; |
| 125 | - StreamPainter& operator=(StreamPainter const&) = delete; |
| 126 | -}; |
| 127 | - |
| 128 | -struct TitlebarUserData::SwappingPainter |
| 129 | - : TitlebarUserData::StreamPainter |
| 130 | -{ |
| 131 | - SwappingPainter(std::shared_ptr<mir::frontend::BufferStream> const& buffer_stream) : |
| 132 | - buffer_stream{buffer_stream}, buffer{nullptr} |
| 133 | - { |
| 134 | - swap_buffers(nullptr); |
| 135 | - } |
| 136 | - |
| 137 | - void swap_buffers(mir::graphics::Buffer* buf) |
| 138 | - { |
| 139 | - auto const callback = [this](mir::graphics::Buffer* new_buffer) |
| 140 | - { |
| 141 | - buffer.store(new_buffer); |
| 142 | - }; |
| 143 | - |
| 144 | - buffer_stream->swap_buffers(buf, callback); |
| 145 | - } |
| 146 | - |
| 147 | - void paint(int intensity) override |
| 148 | - { |
| 149 | - if (auto const buf = buffer.exchange(nullptr)) |
| 150 | - { |
| 151 | - auto const format = buffer_stream->pixel_format(); |
| 152 | - auto const sz = buf->size().height.as_int() * |
| 153 | - buf->size().width.as_int() * MIR_BYTES_PER_PIXEL(format); |
| 154 | - std::vector<unsigned char> pixels(sz, intensity); |
| 155 | - buf->write(pixels.data(), sz); |
| 156 | - swap_buffers(buf); |
| 157 | - } |
| 158 | - } |
| 159 | - |
| 160 | - std::shared_ptr<mir::frontend::BufferStream> const buffer_stream; |
| 161 | - std::atomic<mir::graphics::Buffer*> buffer; |
| 162 | -}; |
| 163 | - |
| 164 | -struct TitlebarUserData::AllocatingPainter |
| 165 | - : TitlebarUserData::StreamPainter |
| 166 | -{ |
| 167 | - AllocatingPainter( |
| 168 | - std::shared_ptr<mir::frontend::BufferStream> const& buffer_stream, |
| 169 | -#if MIR_SERVER_VERSION >= MIR_VERSION_NUMBER(0, 24, 0) |
| 170 | - std::shared_ptr<mir::scene::Session> const& session, |
| 171 | -#endif |
| 172 | - Size size) : |
| 173 | - buffer_stream(buffer_stream), |
| 174 | -#if MIR_SERVER_VERSION >= MIR_VERSION_NUMBER(0, 24, 0) |
| 175 | - session(session), |
| 176 | -#endif |
| 177 | - properties({ |
| 178 | - size, |
| 179 | - buffer_stream->pixel_format(), |
| 180 | - mir::graphics::BufferUsage::software |
| 181 | - }), |
| 182 | -#if MIR_SERVER_VERSION >= MIR_VERSION_NUMBER(0, 24, 0) |
| 183 | - front_buffer(session->create_buffer(properties)), |
| 184 | - back_buffer(session->create_buffer(properties)) |
| 185 | -#else |
| 186 | - front_buffer(buffer_stream->allocate_buffer(properties)), |
| 187 | - back_buffer(buffer_stream->allocate_buffer(properties)) |
| 188 | -#endif |
| 189 | - { |
| 190 | - } |
| 191 | - |
| 192 | - void paint(int intensity) override |
| 193 | - { |
| 194 | -#if MIR_SERVER_VERSION >= MIR_VERSION_NUMBER(0, 24, 0) |
| 195 | - auto buffer = session->get_buffer(back_buffer); |
| 196 | - |
| 197 | - auto const format = buffer->pixel_format(); |
| 198 | - auto const sz = buffer->size().height.as_int() * |
| 199 | - buffer->size().width.as_int() * MIR_BYTES_PER_PIXEL(format); |
| 200 | - std::vector<unsigned char> pixels(sz, intensity); |
| 201 | - buffer->write(pixels.data(), sz); |
| 202 | - buffer_stream->swap_buffers(buffer.get(), [](mir::graphics::Buffer*){}); |
| 203 | -#else |
| 204 | - buffer_stream->with_buffer(back_buffer, |
| 205 | - [this, intensity](mir::graphics::Buffer& buffer) |
| 206 | - { |
| 207 | - auto const format = buffer.pixel_format(); |
| 208 | - auto const sz = buffer.size().height.as_int() * buffer.size().width.as_int() * MIR_BYTES_PER_PIXEL(format); |
| 209 | - std::vector<unsigned char> pixels(sz, intensity); |
| 210 | - buffer.write(pixels.data(), sz); |
| 211 | - buffer_stream->swap_buffers(&buffer, [](mir::graphics::Buffer*){}); |
| 212 | - }); |
| 213 | -#endif |
| 214 | - std::swap(front_buffer, back_buffer); |
| 215 | - } |
| 216 | - |
| 217 | - ~AllocatingPainter() |
| 218 | - { |
| 219 | -#if MIR_SERVER_VERSION >= MIR_VERSION_NUMBER(0, 24, 0) |
| 220 | - session->destroy_buffer(front_buffer); |
| 221 | - session->destroy_buffer(back_buffer); |
| 222 | -#else |
| 223 | - buffer_stream->remove_buffer(front_buffer); |
| 224 | - buffer_stream->remove_buffer(back_buffer); |
| 225 | -#endif |
| 226 | - } |
| 227 | - |
| 228 | - std::shared_ptr<mir::frontend::BufferStream> const buffer_stream; |
| 229 | - std::shared_ptr<mir::scene::Session> const session; |
| 230 | - mir::graphics::BufferProperties properties; |
| 231 | - mir::graphics::BufferID front_buffer; |
| 232 | - mir::graphics::BufferID back_buffer; |
| 233 | -}; |
| 234 | - |
| 235 | -void TitlebarUserData::paint_titlebar(int intensity) |
| 236 | -{ |
| 237 | - if (!stream_painter) |
| 238 | - { |
| 239 | - auto stream = std::shared_ptr<mir::scene::Surface>(window)->primary_buffer_stream(); |
| 240 | - try |
| 241 | - { |
| 242 | - stream_painter = std::make_shared<AllocatingPainter>( |
| 243 | - stream, |
| 244 | -#if MIR_SERVER_VERSION >= MIR_VERSION_NUMBER(0, 24, 0) |
| 245 | - window.application(), |
| 246 | -#endif |
| 247 | - window.size()); |
| 248 | - } |
| 249 | - catch (...) |
| 250 | - { |
| 251 | - stream_painter = std::make_shared<SwappingPainter>(stream); |
| 252 | - } |
| 253 | - } |
| 254 | - |
| 255 | - stream_painter->paint(intensity); |
| 256 | -} |
| 257 | |
| 258 | === removed file 'miral-shell/titlebar/titlebar_user_data.h' |
| 259 | --- miral-shell/titlebar/titlebar_user_data.h 2016-06-07 09:24:55 +0000 |
| 260 | +++ miral-shell/titlebar/titlebar_user_data.h 1970-01-01 00:00:00 +0000 |
| 261 | @@ -1,41 +0,0 @@ |
| 262 | -/* |
| 263 | - * Copyright © 2016 Canonical Ltd. |
| 264 | - * |
| 265 | - * This program is free software: you can redistribute it and/or modify it |
| 266 | - * under the terms of the GNU General Public License version 3, |
| 267 | - * as published by the Free Software Foundation. |
| 268 | - * |
| 269 | - * This program is distributed in the hope that it will be useful, |
| 270 | - * but WITHOUT ANY WARRANTY; without even the implied warranty of |
| 271 | - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
| 272 | - * GNU General Public License for more details. |
| 273 | - * |
| 274 | - * You should have received a copy of the GNU General Public License |
| 275 | - * along with this program. If not, see <http://www.gnu.org/licenses/>. |
| 276 | - * |
| 277 | - * Authored by: Alan Griffiths <alan@octopull.co.uk> |
| 278 | - */ |
| 279 | - |
| 280 | -#ifndef MIRAL_SHELL_TITLEBAR_USER_DATA_H |
| 281 | -#define MIRAL_SHELL_TITLEBAR_USER_DATA_H |
| 282 | - |
| 283 | -#include <miral/window.h> |
| 284 | - |
| 285 | -class TitlebarUserData |
| 286 | -{ |
| 287 | -public: |
| 288 | - TitlebarUserData(miral::Window window) : window{window} { } |
| 289 | - |
| 290 | - void paint_titlebar(int intensity); |
| 291 | - |
| 292 | - miral::Window window; |
| 293 | - |
| 294 | -private: |
| 295 | - struct StreamPainter; |
| 296 | - struct AllocatingPainter; |
| 297 | - struct SwappingPainter; |
| 298 | - |
| 299 | - std::shared_ptr<StreamPainter> stream_painter; |
| 300 | -}; |
| 301 | - |
| 302 | -#endif //MIRAL_SHELL_TITLEBAR_USER_DATA_H |
| 303 | |
| 304 | === added file 'miral-shell/titlebar_provider.cpp' |
| 305 | --- miral-shell/titlebar_provider.cpp 1970-01-01 00:00:00 +0000 |
| 306 | +++ miral-shell/titlebar_provider.cpp 2016-07-07 15:12:19 +0000 |
| 307 | @@ -0,0 +1,276 @@ |
| 308 | +/* |
| 309 | + * Copyright © 2016 Canonical Ltd. |
| 310 | + * |
| 311 | + * This program is free software: you can redistribute it and/or modify it |
| 312 | + * under the terms of the GNU General Public License version 3, |
| 313 | + * as published by the Free Software Foundation. |
| 314 | + * |
| 315 | + * This program is distributed in the hope that it will be useful, |
| 316 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of |
| 317 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
| 318 | + * GNU General Public License for more details. |
| 319 | + * |
| 320 | + * You should have received a copy of the GNU General Public License |
| 321 | + * along with this program. If not, see <http://www.gnu.org/licenses/>. |
| 322 | + * |
| 323 | + * Authored by: Alan Griffiths <alan@octopull.co.uk> |
| 324 | + */ |
| 325 | + |
| 326 | +#include "titlebar_provider.h" |
| 327 | + |
| 328 | +#include <miral/toolkit/surface_spec.h> |
| 329 | + |
| 330 | +#include <mir_toolkit/mir_buffer_stream.h> |
| 331 | + |
| 332 | +#include <cstring> |
| 333 | +#include <sstream> |
| 334 | + |
| 335 | +namespace |
| 336 | +{ |
| 337 | +int const title_bar_height = 10; |
| 338 | + |
| 339 | +void null_surface_callback(MirSurface*, void*) {} |
| 340 | + |
| 341 | +void paint_surface(MirSurface* surface, int const intensity) |
| 342 | +{ |
| 343 | + MirBufferStream* buffer_stream = mir_surface_get_buffer_stream(surface); |
| 344 | + |
| 345 | + // TODO sometimes buffer_stream is nullptr - find out why (and fix). |
| 346 | + // (Only observed when creating a lot of clients at once) |
| 347 | + if (!buffer_stream) |
| 348 | + return; |
| 349 | + |
| 350 | + MirGraphicsRegion region; |
| 351 | + mir_buffer_stream_get_graphics_region(buffer_stream, ®ion); |
| 352 | + |
| 353 | + char* row = region.vaddr; |
| 354 | + |
| 355 | + for (int j = 0; j != region.height; ++j) |
| 356 | + { |
| 357 | + memset(row, intensity, 4*region.width); |
| 358 | + row += region.stride; |
| 359 | + } |
| 360 | + |
| 361 | + mir_buffer_stream_swap_buffers_sync(buffer_stream); |
| 362 | +} |
| 363 | +} |
| 364 | + |
| 365 | +using namespace miral::toolkit; |
| 366 | +using namespace mir::geometry; |
| 367 | + |
| 368 | +TitlebarProvider::TitlebarProvider(miral::WindowManagerTools* const tools) : tools{tools} |
| 369 | +{ |
| 370 | + |
| 371 | +} |
| 372 | + |
| 373 | +TitlebarProvider::~TitlebarProvider() |
| 374 | +{ |
| 375 | + stop(); |
| 376 | +} |
| 377 | + |
| 378 | +void TitlebarProvider::stop() |
| 379 | +{ |
| 380 | + enqueue_work([this] |
| 381 | + { |
| 382 | + std::lock_guard<decltype(mutex)> lock{mutex}; |
| 383 | + window_to_titlebar.clear(); |
| 384 | + connection.reset(); |
| 385 | + stop_work(); |
| 386 | + }); |
| 387 | +} |
| 388 | + |
| 389 | +void TitlebarProvider::operator()(miral::toolkit::Connection connection) |
| 390 | +{ |
| 391 | + this->connection = connection; |
| 392 | + start_work(); |
| 393 | +} |
| 394 | + |
| 395 | +void TitlebarProvider::operator()(std::weak_ptr<mir::scene::Session> const& session) |
| 396 | +{ |
| 397 | + std::lock_guard<decltype(mutex)> lock{mutex}; |
| 398 | + this->weak_session = session; |
| 399 | +} |
| 400 | + |
| 401 | +auto TitlebarProvider::session() const -> std::shared_ptr<mir::scene::Session> |
| 402 | +{ |
| 403 | + std::lock_guard<decltype(mutex)> lock{mutex}; |
| 404 | + return weak_session.lock(); |
| 405 | +} |
| 406 | + |
| 407 | +void TitlebarProvider::create_titlebar_for(miral::Window const& window) |
| 408 | +{ |
| 409 | + enqueue_work([this, window] |
| 410 | + { |
| 411 | + std::ostringstream buffer; |
| 412 | + |
| 413 | + buffer << std::shared_ptr<mir::scene::Surface>(window).get(); |
| 414 | + |
| 415 | + auto const spec = SurfaceSpec::for_normal_surface( |
| 416 | + connection, window.size().width.as_int(), title_bar_height, mir_pixel_format_xrgb_8888) |
| 417 | + .set_buffer_usage(mir_buffer_usage_software) |
| 418 | + .set_type(mir_surface_type_gloss) |
| 419 | + .set_name(buffer.str().c_str()); |
| 420 | + |
| 421 | + std::lock_guard<decltype(mutex)> lock{mutex}; |
| 422 | + spec.create_surface(insert, &window_to_titlebar[window]); |
| 423 | + }); |
| 424 | +} |
| 425 | + |
| 426 | +void TitlebarProvider::paint_titlebar_for(miral::Window const& window, int intensity) |
| 427 | +{ |
| 428 | + if (auto data = find_titlebar_data(window)) |
| 429 | + { |
| 430 | + if (auto surface = data->titlebar.load()) |
| 431 | + { |
| 432 | + enqueue_work([this, surface, intensity]{ paint_surface(surface, intensity); }); |
| 433 | + } |
| 434 | + else |
| 435 | + { |
| 436 | + data->on_create = [this, intensity](MirSurface* surface) |
| 437 | + { enqueue_work([this, surface, intensity]{ paint_surface(surface, intensity); }); }; |
| 438 | + } |
| 439 | + } |
| 440 | +} |
| 441 | + |
| 442 | +void TitlebarProvider::destroy_titlebar_for(miral::Window const& window) |
| 443 | +{ |
| 444 | + enqueue_work([this, window] |
| 445 | + { |
| 446 | + std::lock_guard<decltype(mutex)> lock{mutex}; |
| 447 | + window_to_titlebar.erase(window); |
| 448 | + }); |
| 449 | +} |
| 450 | + |
| 451 | +void TitlebarProvider::resize_titlebar_for(miral::Window const& window, Size const& size) |
| 452 | +{ |
| 453 | + if (window.size().width == size.width) |
| 454 | + return; |
| 455 | + |
| 456 | + if (auto titlebar_window = find_titlebar_window(window)) |
| 457 | + { |
| 458 | + titlebar_window.resize({size.width, title_bar_height}); |
| 459 | + } |
| 460 | +} |
| 461 | + |
| 462 | +void TitlebarProvider::advise_new_titlebar(miral::WindowInfo& window_info) |
| 463 | +{ |
| 464 | + std::istringstream buffer{window_info.name()}; |
| 465 | + |
| 466 | + void* parent = nullptr; |
| 467 | + buffer >> parent; |
| 468 | + |
| 469 | + std::lock_guard<decltype(mutex)> lock{mutex}; |
| 470 | + |
| 471 | + for (auto& element : window_to_titlebar) |
| 472 | + { |
| 473 | + auto scene_surface = std::shared_ptr<mir::scene::Surface>(element.first); |
| 474 | + if (scene_surface.get() == parent) |
| 475 | + { |
| 476 | + auto window = window_info.window(); |
| 477 | + element.second.window = window; |
| 478 | + auto& parent_info = tools->info_for(scene_surface); |
| 479 | + parent_info.add_child(window); |
| 480 | + window_info.parent(parent_info.window()); |
| 481 | + window.move_to(parent_info.window().top_left() - Displacement{0, title_bar_height}); |
| 482 | + break; |
| 483 | + } |
| 484 | + } |
| 485 | +} |
| 486 | + |
| 487 | +void TitlebarProvider::advise_state_change(miral::WindowInfo const& window_info, MirSurfaceState state, Rectangle const& display_area) |
| 488 | +{ |
| 489 | + if (auto window = find_titlebar_window(window_info.window())) |
| 490 | + { |
| 491 | + switch (state) |
| 492 | + { |
| 493 | + case mir_surface_state_restored: |
| 494 | + window.resize({window_info.restore_rect().size.width, title_bar_height}); |
| 495 | + window.show(); |
| 496 | + break; |
| 497 | + |
| 498 | + case mir_surface_state_maximized: |
| 499 | + case mir_surface_state_vertmaximized: |
| 500 | + case mir_surface_state_hidden: |
| 501 | + case mir_surface_state_minimized: |
| 502 | + window.hide(); |
| 503 | + break; |
| 504 | + |
| 505 | + case mir_surface_state_horizmaximized: |
| 506 | + window.resize({display_area.size.width, title_bar_height}); |
| 507 | + window.show(); |
| 508 | + break; |
| 509 | + |
| 510 | + case mir_surface_state_fullscreen: |
| 511 | + default: |
| 512 | + break; |
| 513 | + } |
| 514 | + } |
| 515 | +} |
| 516 | + |
| 517 | +TitlebarProvider::Data::~Data() |
| 518 | +{ |
| 519 | + if (auto const surface = titlebar.load()) |
| 520 | + mir_surface_release(surface, &null_surface_callback, nullptr); |
| 521 | +} |
| 522 | + |
| 523 | +void TitlebarProvider::insert(MirSurface* surface, Data* data) |
| 524 | +{ |
| 525 | + data->on_create(surface); |
| 526 | + data->titlebar = surface; |
| 527 | +} |
| 528 | + |
| 529 | +TitlebarProvider::Data* TitlebarProvider::find_titlebar_data(miral::Window const& window) |
| 530 | +{ |
| 531 | + std::lock_guard<decltype(mutex)> lock{mutex}; |
| 532 | + |
| 533 | + auto const find = window_to_titlebar.find(window); |
| 534 | + |
| 535 | + return (find != window_to_titlebar.end()) ? &find->second : nullptr; |
| 536 | +} |
| 537 | + |
| 538 | +miral::Window TitlebarProvider::find_titlebar_window(miral::Window const& window) const |
| 539 | +{ |
| 540 | + std::lock_guard<decltype(mutex)> lock{mutex}; |
| 541 | + |
| 542 | + auto const find = window_to_titlebar.find(window); |
| 543 | + |
| 544 | + return (find != window_to_titlebar.end()) ? find->second.window : miral::Window{}; |
| 545 | +} |
| 546 | + |
| 547 | +Worker::~Worker() |
| 548 | +{ |
| 549 | + if (worker.joinable()) worker.join(); |
| 550 | +} |
| 551 | + |
| 552 | +void Worker::do_work() |
| 553 | +{ |
| 554 | + while (!work_done) |
| 555 | + { |
| 556 | + WorkQueue::value_type work; |
| 557 | + { |
| 558 | + std::unique_lock<decltype(work_mutex)> lock{work_mutex}; |
| 559 | + work_cv.wait(lock, [this] { return !work_queue.empty(); }); |
| 560 | + work = work_queue.front(); |
| 561 | + work_queue.pop(); |
| 562 | + } |
| 563 | + |
| 564 | + work(); |
| 565 | + } |
| 566 | +} |
| 567 | + |
| 568 | +void Worker::enqueue_work(std::function<void()> const& functor) |
| 569 | +{ |
| 570 | + std::lock_guard<decltype(work_mutex)> lock{work_mutex}; |
| 571 | + work_queue.push(functor); |
| 572 | + work_cv.notify_one(); |
| 573 | +} |
| 574 | + |
| 575 | +void Worker::start_work() |
| 576 | +{ |
| 577 | + worker = std::thread{[this] { do_work(); }}; |
| 578 | +} |
| 579 | + |
| 580 | +void Worker::stop_work() |
| 581 | +{ |
| 582 | + enqueue_work([this] { work_done = true; }); |
| 583 | +} |
| 584 | \ No newline at end of file |
| 585 | |
| 586 | === added file 'miral-shell/titlebar_provider.h' |
| 587 | --- miral-shell/titlebar_provider.h 1970-01-01 00:00:00 +0000 |
| 588 | +++ miral-shell/titlebar_provider.h 2016-07-07 15:12:19 +0000 |
| 589 | @@ -0,0 +1,102 @@ |
| 590 | +/* |
| 591 | + * Copyright © 2016 Canonical Ltd. |
| 592 | + * |
| 593 | + * This program is free software: you can redistribute it and/or modify it |
| 594 | + * under the terms of the GNU General Public License version 3, |
| 595 | + * as published by the Free Software Foundation. |
| 596 | + * |
| 597 | + * This program is distributed in the hope that it will be useful, |
| 598 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of |
| 599 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
| 600 | + * GNU General Public License for more details. |
| 601 | + * |
| 602 | + * You should have received a copy of the GNU General Public License |
| 603 | + * along with this program. If not, see <http://www.gnu.org/licenses/>. |
| 604 | + * |
| 605 | + * Authored by: Alan Griffiths <alan@octopull.co.uk> |
| 606 | + */ |
| 607 | + |
| 608 | +#ifndef MIRAL_SHELL_TITLEBAR_PROVIDER_H |
| 609 | +#define MIRAL_SHELL_TITLEBAR_PROVIDER_H |
| 610 | + |
| 611 | + |
| 612 | +#include <miral/window_manager_tools.h> |
| 613 | + |
| 614 | +#include <mir/geometry/rectangle.h> |
| 615 | +#include <mir_toolkit/client_types.h> |
| 616 | + |
| 617 | +#include <atomic> |
| 618 | +#include <map> |
| 619 | +#include <mutex> |
| 620 | +#include <miral/toolkit/connection.h> |
| 621 | +#include <thread> |
| 622 | +#include <condition_variable> |
| 623 | +#include <queue> |
| 624 | + |
| 625 | +class Worker |
| 626 | +{ |
| 627 | +public: |
| 628 | + ~Worker(); |
| 629 | + |
| 630 | + void start_work(); |
| 631 | + void enqueue_work(std::function<void()> const& functor); |
| 632 | + void stop_work(); |
| 633 | + |
| 634 | +private: |
| 635 | + using WorkQueue = std::queue<std::function<void()>>; |
| 636 | + |
| 637 | + std::mutex mutable work_mutex; |
| 638 | + std::condition_variable work_cv; |
| 639 | + WorkQueue work_queue; |
| 640 | + bool work_done = false; |
| 641 | + std::thread worker; |
| 642 | + |
| 643 | + void do_work(); |
| 644 | +}; |
| 645 | + |
| 646 | +class TitlebarProvider : Worker |
| 647 | +{ |
| 648 | +public: |
| 649 | + TitlebarProvider(miral::WindowManagerTools* const tools); |
| 650 | + ~TitlebarProvider(); |
| 651 | + |
| 652 | + void operator()(miral::toolkit::Connection connection); |
| 653 | + void operator()(std::weak_ptr<mir::scene::Session> const& session); |
| 654 | + |
| 655 | + auto session() const -> std::shared_ptr<mir::scene::Session>; |
| 656 | + |
| 657 | + void create_titlebar_for(miral::Window const& window); |
| 658 | + void paint_titlebar_for(miral::Window const& window, int intensity); |
| 659 | + void destroy_titlebar_for(miral::Window const& window); |
| 660 | + void resize_titlebar_for(miral::Window const& window, mir::geometry::Size const& size); |
| 661 | + void advise_new_titlebar(miral::WindowInfo& window_info); |
| 662 | + void advise_state_change(miral::WindowInfo const& window_info, MirSurfaceState state, mir::geometry::Rectangle const& display_area); |
| 663 | + |
| 664 | + void stop(); |
| 665 | + |
| 666 | +private: |
| 667 | + struct Data |
| 668 | + { |
| 669 | + std::atomic<MirSurface*> titlebar{nullptr}; |
| 670 | + std::function<void(MirSurface* surface)> on_create{[](MirSurface*){}}; |
| 671 | + miral::Window window; |
| 672 | + |
| 673 | + ~Data(); |
| 674 | + }; |
| 675 | + |
| 676 | + using SurfaceMap = std::map<std::weak_ptr<mir::scene::Surface>, Data, std::owner_less<std::weak_ptr<mir::scene::Surface>>>; |
| 677 | + |
| 678 | + miral::WindowManagerTools* const tools; |
| 679 | + std::mutex mutable mutex; |
| 680 | + miral::toolkit::Connection connection; |
| 681 | + std::weak_ptr<mir::scene::Session> weak_session; |
| 682 | + |
| 683 | + SurfaceMap window_to_titlebar; |
| 684 | + |
| 685 | + static void insert(MirSurface* surface, Data* data); |
| 686 | + Data* find_titlebar_data(miral::Window const& window); |
| 687 | + miral::Window find_titlebar_window(miral::Window const& window) const; |
| 688 | +}; |
| 689 | + |
| 690 | + |
| 691 | +#endif //MIRAL_SHELL_TITLEBAR_PROVIDER_H |
| 692 | |
| 693 | === modified file 'miral-shell/titlebar_window_manager.cpp' |
| 694 | --- miral-shell/titlebar_window_manager.cpp 2016-06-17 16:50:29 +0000 |
| 695 | +++ miral-shell/titlebar_window_manager.cpp 2016-07-07 15:12:19 +0000 |
| 696 | @@ -17,38 +17,32 @@ |
| 697 | */ |
| 698 | |
| 699 | #include "titlebar_window_manager.h" |
| 700 | -#include "titlebar/titlebar_user_data.h" |
| 701 | +#include "titlebar_provider.h" |
| 702 | |
| 703 | #include <miral/application_info.h> |
| 704 | +#include <miral/internal_client.h> |
| 705 | #include <miral/window_info.h> |
| 706 | #include <miral/window_manager_tools.h> |
| 707 | |
| 708 | +#include <linux/input.h> |
| 709 | + |
| 710 | using namespace miral; |
| 711 | |
| 712 | -namespace |
| 713 | -{ |
| 714 | -int const title_bar_height = 10; |
| 715 | -Size titlebar_size_for_window(Size window_size) |
| 716 | -{ |
| 717 | - return {window_size.width, Height{title_bar_height}}; |
| 718 | -} |
| 719 | - |
| 720 | -Point titlebar_position_for_window(Point window_position) |
| 721 | -{ |
| 722 | - return { |
| 723 | - window_position.x, |
| 724 | - window_position.y - DeltaY(title_bar_height) |
| 725 | - }; |
| 726 | -} |
| 727 | -} |
| 728 | - |
| 729 | -TitlebarWindowManagerPolicy::TitlebarWindowManagerPolicy(WindowManagerTools* const tools, SpinnerSplash const& spinner) : |
| 730 | + |
| 731 | +TitlebarWindowManagerPolicy::TitlebarWindowManagerPolicy( |
| 732 | + WindowManagerTools* const tools, |
| 733 | + SpinnerSplash const& spinner, |
| 734 | + miral::InternalClientLauncher const& launcher) : |
| 735 | CanonicalWindowManagerPolicy(tools), |
| 736 | tools(tools), |
| 737 | - spinner{spinner} |
| 738 | + spinner{spinner}, |
| 739 | + titlebar_provider{std::make_unique<TitlebarProvider>(tools)} |
| 740 | { |
| 741 | + launcher.launch("decorations", *titlebar_provider); |
| 742 | } |
| 743 | |
| 744 | +TitlebarWindowManagerPolicy::~TitlebarWindowManagerPolicy() = default; |
| 745 | + |
| 746 | bool TitlebarWindowManagerPolicy::handle_pointer_event(MirPointerEvent const* event) |
| 747 | { |
| 748 | auto consumes_event = CanonicalWindowManagerPolicy::handle_pointer_event(event); |
| 749 | @@ -64,24 +58,14 @@ |
| 750 | { |
| 751 | if (mir_pointer_event_button_state(event, mir_pointer_button_primary)) |
| 752 | { |
| 753 | - // TODO this is a rather roundabout way to detect a titlebar |
| 754 | if (auto const possible_titlebar = tools->window_at(old_cursor)) |
| 755 | { |
| 756 | - if (auto const parent = tools->info_for(possible_titlebar).parent()) |
| 757 | + if (possible_titlebar.application() == titlebar_provider->session()) |
| 758 | { |
| 759 | - if (auto const& parent_userdata = |
| 760 | - std::static_pointer_cast<TitlebarUserData>(tools->info_for(parent).userdata())) |
| 761 | - { |
| 762 | - if (possible_titlebar == parent_userdata->window) |
| 763 | - { |
| 764 | - if (auto const target = tools->window_at(old_cursor)) |
| 765 | - { |
| 766 | - tools->select_active_window(target); |
| 767 | - tools->drag_active_window(cursor - old_cursor); |
| 768 | - } |
| 769 | - consumes_event = true; |
| 770 | - } |
| 771 | - } |
| 772 | + auto const& info = tools->info_for(possible_titlebar); |
| 773 | + tools->select_active_window(info.parent()); |
| 774 | + tools->drag_active_window(cursor - old_cursor); |
| 775 | + consumes_event = true; |
| 776 | } |
| 777 | } |
| 778 | } |
| 779 | @@ -96,47 +80,33 @@ |
| 780 | { |
| 781 | CanonicalWindowManagerPolicy::advise_new_window(window_info); |
| 782 | |
| 783 | - if (!window_info.needs_titlebar(window_info.type())) |
| 784 | - return; |
| 785 | - |
| 786 | - Window const& window = window_info.window(); |
| 787 | - |
| 788 | - auto format = mir_pixel_format_xrgb_8888; |
| 789 | - WindowSpecification params; |
| 790 | - params.size() = titlebar_size_for_window(window.size()); |
| 791 | - params.name() = "decoration"; |
| 792 | - params.pixel_format() = format; |
| 793 | - params.buffer_usage() = WindowSpecification::BufferUsage::software; |
| 794 | - params.top_left() = titlebar_position_for_window(window.top_left()); |
| 795 | - params.type() = mir_surface_type_gloss; |
| 796 | - |
| 797 | - auto& titlebar_info = tools->build_window(window.application(), params); |
| 798 | - titlebar_info.window().set_alpha(0.9); |
| 799 | - titlebar_info.parent(window); |
| 800 | - |
| 801 | - auto data = std::make_shared<TitlebarUserData>(titlebar_info.window()); |
| 802 | - window_info.userdata(data); |
| 803 | - window_info.add_child(titlebar_info.window()); |
| 804 | + auto const application = window_info.window().application(); |
| 805 | + |
| 806 | + if (application == titlebar_provider->session()) |
| 807 | + { |
| 808 | + titlebar_provider->advise_new_titlebar(window_info); |
| 809 | + tools->raise_tree(window_info.parent()); |
| 810 | + return; |
| 811 | + } |
| 812 | + |
| 813 | + if (application == spinner.session() || !window_info.needs_titlebar(window_info.type())) |
| 814 | + return; |
| 815 | + |
| 816 | + titlebar_provider->create_titlebar_for(window_info.window()); |
| 817 | } |
| 818 | |
| 819 | void TitlebarWindowManagerPolicy::advise_focus_lost(WindowInfo const& info) |
| 820 | { |
| 821 | CanonicalWindowManagerPolicy::advise_focus_lost(info); |
| 822 | |
| 823 | - if (auto const titlebar = std::static_pointer_cast<TitlebarUserData>(info.userdata())) |
| 824 | - { |
| 825 | - titlebar->paint_titlebar(0x3F); |
| 826 | - } |
| 827 | + titlebar_provider->paint_titlebar_for(info.window(), 0x3F); |
| 828 | } |
| 829 | |
| 830 | void TitlebarWindowManagerPolicy::advise_focus_gained(WindowInfo const& info) |
| 831 | { |
| 832 | CanonicalWindowManagerPolicy::advise_focus_gained(info); |
| 833 | |
| 834 | - if (auto const titlebar = std::static_pointer_cast<TitlebarUserData>(info.userdata())) |
| 835 | - { |
| 836 | - titlebar->paint_titlebar(0xFF); |
| 837 | - } |
| 838 | + titlebar_provider->paint_titlebar_for(info.window(), 0xFF); |
| 839 | |
| 840 | // Frig to force the spinner to the top |
| 841 | if (auto const spinner_session = spinner.session()) |
| 842 | @@ -152,52 +122,21 @@ |
| 843 | { |
| 844 | CanonicalWindowManagerPolicy::advise_state_change(window_info, state); |
| 845 | |
| 846 | - if (auto const titlebar = std::static_pointer_cast<TitlebarUserData>(window_info.userdata())) |
| 847 | - { |
| 848 | - switch (state) |
| 849 | - { |
| 850 | - case mir_surface_state_restored: |
| 851 | - titlebar->window.resize(titlebar_size_for_window(window_info.restore_rect().size)); |
| 852 | - titlebar->window.show(); |
| 853 | - break; |
| 854 | - |
| 855 | - case mir_surface_state_maximized: |
| 856 | - case mir_surface_state_vertmaximized: |
| 857 | - case mir_surface_state_hidden: |
| 858 | - case mir_surface_state_minimized: |
| 859 | - titlebar->window.hide(); |
| 860 | - break; |
| 861 | - |
| 862 | - case mir_surface_state_horizmaximized: |
| 863 | - titlebar->window.resize(titlebar_size_for_window({display_area.size.width, window_info.restore_rect().size.height})); |
| 864 | - titlebar->window.show(); |
| 865 | - break; |
| 866 | - |
| 867 | - case mir_surface_state_fullscreen: |
| 868 | - default: |
| 869 | - break; |
| 870 | - } |
| 871 | - } |
| 872 | + titlebar_provider->advise_state_change(window_info, state, display_area); |
| 873 | } |
| 874 | |
| 875 | void TitlebarWindowManagerPolicy::advise_resize(WindowInfo const& window_info, Size const& new_size) |
| 876 | { |
| 877 | CanonicalWindowManagerPolicy::advise_resize(window_info, new_size); |
| 878 | |
| 879 | - if (auto const titlebar = std::static_pointer_cast<TitlebarUserData>(window_info.userdata())) |
| 880 | - { |
| 881 | - titlebar->window.resize({new_size.width, Height{title_bar_height}}); |
| 882 | - } |
| 883 | + titlebar_provider->resize_titlebar_for(window_info.window(), new_size); |
| 884 | } |
| 885 | |
| 886 | void TitlebarWindowManagerPolicy::advise_delete_window(WindowInfo const& window_info) |
| 887 | { |
| 888 | CanonicalWindowManagerPolicy::advise_delete_window(window_info); |
| 889 | |
| 890 | - if (auto const titlebar = std::static_pointer_cast<TitlebarUserData>(window_info.userdata())) |
| 891 | - { |
| 892 | - tools->destroy(titlebar->window); |
| 893 | - } |
| 894 | + titlebar_provider->destroy_titlebar_for(window_info.window()); |
| 895 | } |
| 896 | |
| 897 | void TitlebarWindowManagerPolicy::handle_displays_updated(Rectangles const& displays) |
| 898 | @@ -206,3 +145,23 @@ |
| 899 | |
| 900 | display_area = displays.bounding_rectangle(); |
| 901 | } |
| 902 | + |
| 903 | +bool TitlebarWindowManagerPolicy::handle_keyboard_event(MirKeyboardEvent const* event) |
| 904 | +{ |
| 905 | + if (miral::CanonicalWindowManagerPolicy::handle_keyboard_event(event)) |
| 906 | + return true; |
| 907 | + |
| 908 | + // TODO this is a workaround for the lack of a way to detect server exit (Mir bug lp:1593655) |
| 909 | + // We need to exit the titlebar_provider "client" thread before the server exits |
| 910 | + auto const action = mir_keyboard_event_action(event); |
| 911 | + auto const scan_code = mir_keyboard_event_scan_code(event); |
| 912 | + auto const modifiers = mir_keyboard_event_modifiers(event) & modifier_mask; |
| 913 | + |
| 914 | + if (action == mir_keyboard_action_down && scan_code == KEY_BACKSPACE && |
| 915 | + (modifiers == (mir_input_event_modifier_alt | mir_input_event_modifier_ctrl))) |
| 916 | + { |
| 917 | + titlebar_provider->stop(); |
| 918 | + } |
| 919 | + |
| 920 | + return false; |
| 921 | +} |
| 922 | |
| 923 | === modified file 'miral-shell/titlebar_window_manager.h' |
| 924 | --- miral-shell/titlebar_window_manager.h 2016-06-17 16:50:29 +0000 |
| 925 | +++ miral-shell/titlebar_window_manager.h 2016-07-07 15:12:19 +0000 |
| 926 | @@ -23,14 +23,20 @@ |
| 927 | |
| 928 | #include <miral/canonical_window_manager.h> |
| 929 | |
| 930 | +namespace miral { class InternalClientLauncher; } |
| 931 | + |
| 932 | using namespace mir::geometry; |
| 933 | |
| 934 | +class TitlebarProvider; |
| 935 | + |
| 936 | class TitlebarWindowManagerPolicy : public miral::CanonicalWindowManagerPolicy |
| 937 | { |
| 938 | public: |
| 939 | - TitlebarWindowManagerPolicy(miral::WindowManagerTools* const tools, SpinnerSplash const& spinner); |
| 940 | + TitlebarWindowManagerPolicy(miral::WindowManagerTools* const tools, SpinnerSplash const& spinner, miral::InternalClientLauncher const& launcher); |
| 941 | + ~TitlebarWindowManagerPolicy(); |
| 942 | |
| 943 | bool handle_pointer_event(MirPointerEvent const* event) override; |
| 944 | + bool handle_keyboard_event(MirKeyboardEvent const* event) override; |
| 945 | |
| 946 | void advise_new_window(miral::WindowInfo& window_info) override; |
| 947 | void advise_focus_lost(miral::WindowInfo const& info) override; |
| 948 | @@ -40,10 +46,13 @@ |
| 949 | void advise_delete_window(miral::WindowInfo const& window_info) override; |
| 950 | |
| 951 | void handle_displays_updated(Rectangles const& displays) override; |
| 952 | + |
| 953 | private: |
| 954 | miral::WindowManagerTools* const tools; |
| 955 | SpinnerSplash const spinner; |
| 956 | |
| 957 | + std::unique_ptr<TitlebarProvider> const titlebar_provider; |
| 958 | + |
| 959 | Rectangle display_area; |
| 960 | Point old_cursor{}; |
| 961 | }; |
| 962 | |
| 963 | === modified file 'miral/application.cpp' |
| 964 | --- miral/application.cpp 2016-04-22 09:24:24 +0000 |
| 965 | +++ miral/application.cpp 2016-07-07 15:12:19 +0000 |
| 966 | @@ -20,10 +20,17 @@ |
| 967 | |
| 968 | #include <mir/scene/session.h> |
| 969 | |
| 970 | +#include <unistd.h> |
| 971 | + |
| 972 | #include <csignal> |
| 973 | |
| 974 | void miral::kill(Application const& application, int sig) |
| 975 | { |
| 976 | if (application) |
| 977 | - ::kill(application->process_id(), sig); |
| 978 | + { |
| 979 | + auto const pid = application->process_id(); |
| 980 | + |
| 981 | + if (pid != getpid()) |
| 982 | + ::kill(pid, sig); |
| 983 | + } |
| 984 | } |
| 985 | |
| 986 | === modified file 'miral/basic_window_manager.cpp' |
| 987 | --- miral/basic_window_manager.cpp 2016-06-17 16:50:29 +0000 |
| 988 | +++ miral/basic_window_manager.cpp 2016-07-07 15:12:19 +0000 |
| 989 | @@ -69,15 +69,6 @@ |
| 990 | { |
| 991 | auto spec = spec_; |
| 992 | |
| 993 | -#if MIR_SERVER_VERSION >= MIR_VERSION_NUMBER(0, 22, 0) |
| 994 | - // Quick, dirty hack to support titlebar creation - really need an API for buffer stream creation |
| 995 | - if (!spec.content_id().is_set() && !spec.streams().is_set()) |
| 996 | - { |
| 997 | - mir::graphics::BufferProperties properties(spec.size().value(), spec.pixel_format().value(), mir::graphics::BufferUsage::software); |
| 998 | - spec.content_id() = BufferStreamId{application->create_buffer_stream(properties).as_value()}; |
| 999 | - } |
| 1000 | -#endif |
| 1001 | - |
| 1002 | auto result = surface_builder(application, spec); |
| 1003 | auto& info = window_info.emplace(result, WindowInfo{result, spec}).first->second; |
| 1004 | if (spec.parent().is_set() && spec.parent().value().lock()) |
| 1005 | @@ -202,13 +193,6 @@ |
| 1006 | } |
| 1007 | } |
| 1008 | |
| 1009 | -void miral::BasicWindowManager::destroy(Window& window) |
| 1010 | -{ |
| 1011 | - erase(info_for(window)); |
| 1012 | - |
| 1013 | - window.application()->destroy_surface(window); |
| 1014 | -} |
| 1015 | - |
| 1016 | void miral::BasicWindowManager::erase(miral::WindowInfo const& info) |
| 1017 | { |
| 1018 | if (auto const parent = info.parent()) |
| 1019 | @@ -901,7 +885,7 @@ |
| 1020 | { |
| 1021 | // select_active_window() calls set_focus_to() which updates mru_active_windows and changes window |
| 1022 | auto const w = window; |
| 1023 | - return w.application() != session || !(new_focus = miral::BasicWindowManager::select_active_window(w)); |
| 1024 | + return w.application() != session || !(new_focus = select_active_window(w)); |
| 1025 | }); |
| 1026 | |
| 1027 | return new_focus; |
| 1028 | |
| 1029 | === modified file 'miral/basic_window_manager.h' |
| 1030 | --- miral/basic_window_manager.h 2016-06-17 16:50:29 +0000 |
| 1031 | +++ miral/basic_window_manager.h 2016-07-07 15:12:19 +0000 |
| 1032 | @@ -55,9 +55,6 @@ |
| 1033 | std::shared_ptr<mir::shell::DisplayLayout> const& display_layout, |
| 1034 | WindowManagementPolicyBuilder const& build); |
| 1035 | |
| 1036 | - auto build_window(Application const& application, WindowSpecification const& spec) |
| 1037 | - -> WindowInfo& override; |
| 1038 | - |
| 1039 | void add_session(std::shared_ptr<mir::scene::Session> const& session) override; |
| 1040 | |
| 1041 | void remove_session(std::shared_ptr<mir::scene::Session> const& session) override; |
| 1042 | @@ -77,8 +74,6 @@ |
| 1043 | std::shared_ptr<mir::scene::Session> const& session, |
| 1044 | std::weak_ptr<mir::scene::Surface> const& surface) override; |
| 1045 | |
| 1046 | - void destroy(Window& window) override; |
| 1047 | - |
| 1048 | void add_display(mir::geometry::Rectangle const& area) override; |
| 1049 | |
| 1050 | void remove_display(mir::geometry::Rectangle const& area) override; |
| 1051 | @@ -168,6 +163,8 @@ |
| 1052 | |
| 1053 | auto place_new_surface(ApplicationInfo const& app_info, WindowSpecification parameters) |
| 1054 | -> WindowSpecification; |
| 1055 | + auto build_window(Application const& application, WindowSpecification const& spec) |
| 1056 | + -> WindowInfo&; |
| 1057 | void move_tree(miral::WindowInfo& root, mir::geometry::Displacement movement); |
| 1058 | void erase(miral::WindowInfo const& info); |
| 1059 | }; |

Looks good.