Merge lp:~3v1n0/unity/decoration-edges-improvements into lp:unity

Proposed by Marco Trevisan (Treviño) on 2014-10-01
Status: Merged
Approved by: Marco Trevisan (Treviño) on 2014-10-16
Approved revision: 3837
Merged at revision: 3882
Proposed branch: lp:~3v1n0/unity/decoration-edges-improvements
Merge into: lp:unity
Diff against target: 1018 lines (+333/-177)
13 files modified
UnityCore/DesktopUtilities.cpp (+0/-2)
decorations/DecoratedWindow.cpp (+139/-64)
decorations/DecorationsEdgeBorders.cpp (+32/-19)
decorations/DecorationsForceQuitDialog.cpp (+17/-3)
decorations/DecorationsManager.cpp (+16/-25)
decorations/DecorationsPriv.h (+11/-3)
decorations/DecorationsTitle.cpp (+1/-0)
decorations/DecorationsWidgets.cpp (+13/-1)
decorations/DecorationsWidgets.h (+5/-0)
plugins/unityshell/src/unityshell.cpp (+1/-0)
unity-shared/CompizUtils.cpp (+73/-54)
unity-shared/CompizUtils.h (+24/-5)
unity-shared/XWindowManager.cpp (+1/-1)
To merge this branch: bzr merge lp:~3v1n0/unity/decoration-edges-improvements
Reviewer Review Type Date Requested Status
PS Jenkins bot (community) continuous-integration Approve on 2014-10-10
Brandon Schaefer (community) 2014-10-01 Approve on 2014-10-01
Review via email: mp+236744@code.launchpad.net

Commit message

DecoratedWindow: make edges independent from borders and properly update them on actions changed

Now windows can have edges (handles) also if they are not fully decorated, and
the other way around.
Improved the logic to detect which kind of decorations are supported by windows
(so now we add shadows to windows with borders, and we do not to shaped ones).
Removed a lot of duplicated matrix/region computations.
Properly rebuild decorations when _NET_WM_ALLOWED_ACTIONS changes
Fixes to the ForceQuit dialog shadows (and support for backdrop mode).

To post a comment you must log in.
3836. By Marco Trevisan (Treviño) on 2014-10-01

DecoratedWindow: some code cleanup

PS Jenkins bot (ps-jenkins) wrote :
review: Approve (continuous-integration)
Brandon Schaefer (brandontschaefer) wrote :

LGTM

review: Approve
PS Jenkins bot (ps-jenkins) wrote :
review: Approve (continuous-integration)
3837. By Marco Trevisan (Treviño) on 2014-10-10

DecorationsManager: update the active window only on _NET_ACTIVE_WINDOW updates

PS Jenkins bot (ps-jenkins) wrote :
review: Approve (continuous-integration)

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'UnityCore/DesktopUtilities.cpp'
2--- UnityCore/DesktopUtilities.cpp 2014-08-26 22:59:57 +0000
3+++ UnityCore/DesktopUtilities.cpp 2014-10-10 14:56:03 +0000
4@@ -71,8 +71,6 @@
5 const char *config_dir = g_get_user_config_dir();
6 auto unity_config = glib::gchar_to_string(config_dir).append(G_DIR_SEPARATOR_S "unity" G_DIR_SEPARATOR_S);
7
8- printf("CONFIG %s\n", unity_config.c_str());
9-
10 if (g_mkdir_with_parents(unity_config.c_str(), 0700) >= 0)
11 return unity_config;
12
13
14=== modified file 'decorations/DecoratedWindow.cpp'
15--- decorations/DecoratedWindow.cpp 2014-07-30 00:49:35 +0000
16+++ decorations/DecoratedWindow.cpp 2014-10-10 14:56:03 +0000
17@@ -1,6 +1,6 @@
18 // -*- Mode: C++; indent-tabs-mode: nil; tab-width: 2 -*-
19 /*
20- * Copyright (C) 2013 Canonical Ltd
21+ * Copyright (C) 2013-2014 Canonical Ltd
22 *
23 * This program is free software: you can redistribute it and/or modify
24 * it under the terms of the GNU General Public License version 3 as
25@@ -44,8 +44,12 @@
26 , cwin_(CompositeWindow::get(win_))
27 , glwin_(GLWindow::get(win_))
28 , frame_(0)
29+ , monitor_(0)
30 , dirty_geo_(true)
31- , monitor_(0)
32+ , dirty_frame_(false)
33+ , deco_elements_(cu::DecorationElement::NONE)
34+ , last_mwm_decor_(win_->mwmDecor())
35+ , last_actions_(win_->actions())
36 , cv_(Settings::Instance().em())
37 {
38 active.changed.connect([this] (bool active) {
39@@ -105,14 +109,27 @@
40
41 void Window::Impl::Update()
42 {
43- ShouldBeDecorated() ? Decorate() : Undecorate();
44+ UpdateElements();
45+ (deco_elements_ & (cu::DecorationElement::EDGE | cu::DecorationElement::BORDER)) ? Decorate() : Undecorate();
46+ last_mwm_decor_ = win_->mwmDecor();
47+ last_actions_ = win_->actions();
48 }
49
50 void Window::Impl::Decorate()
51 {
52 SetupExtents();
53 UpdateFrame();
54- SetupWindowControls();
55+ SetupWindowEdges();
56+
57+ if (deco_elements_ & cu::DecorationElement::BORDER)
58+ {
59+ SetupWindowControls();
60+ }
61+ else
62+ {
63+ CleanupWindowControls();
64+ bg_textures_.clear();
65+ }
66 }
67
68 void Window::Impl::Undecorate()
69@@ -120,6 +137,7 @@
70 UnsetExtents();
71 UnsetFrame();
72 CleanupWindowControls();
73+ CleanupWindowEdges();
74 bg_textures_.clear();
75 }
76
77@@ -139,17 +157,27 @@
78 if (win_->hasUnmapReference())
79 return;
80
81- auto const& sb = Style::Get()->Border();
82- CompWindowExtents border(cv_->CP(sb.left),
83- cv_->CP(sb.right),
84- cv_->CP(sb.top),
85- cv_->CP(sb.bottom));
86-
87- auto const& ib = Style::Get()->InputBorder();
88- CompWindowExtents input(cv_->CP(sb.left + ib.left),
89- cv_->CP(sb.right + ib.right),
90- cv_->CP(sb.top + ib.top),
91- cv_->CP(sb.bottom + ib.bottom));
92+ CompWindowExtents border;
93+
94+ if (deco_elements_ & cu::DecorationElement::BORDER)
95+ {
96+ auto const& sb = Style::Get()->Border();
97+ border.left = cv_->CP(sb.left);
98+ border.right = cv_->CP(sb.right);
99+ border.top = cv_->CP(sb.top);
100+ border.bottom = cv_->CP(sb.bottom);
101+ }
102+
103+ CompWindowExtents input(border);
104+
105+ if (deco_elements_ & cu::DecorationElement::EDGE)
106+ {
107+ auto const& ib = Style::Get()->InputBorder();
108+ input.left += cv_->CP(ib.left);
109+ input.right += cv_->CP(ib.right);
110+ input.top += cv_->CP(ib.top);
111+ input.bottom += cv_->CP(ib.bottom);
112+ }
113
114 if (win_->border() != border || win_->input() != input)
115 win_->setWindowFrameExtents(&border, &input);
116@@ -183,6 +211,15 @@
117 UpdateFrameGeo(frame_geo);
118 }
119
120+void Window::Impl::UpdateFrameActions()
121+{
122+ if (!dirty_frame_ && (win_->mwmDecor() != last_mwm_decor_ || win_->actions() != last_actions_))
123+ {
124+ dirty_frame_ = true;
125+ Damage();
126+ }
127+}
128+
129 void Window::Impl::CreateFrame(nux::Geometry const& frame_geo)
130 {
131 /* Since we're reparenting windows here, we need to grab the server
132@@ -280,6 +317,42 @@
133 win_->updateFrameRegion();
134 }
135
136+void Window::Impl::SetupWindowEdges()
137+{
138+ if (input_mixer_)
139+ return;
140+
141+ dpi_changed_ = Settings::Instance().dpi_changed.connect([this] {
142+ Update();
143+ edge_borders_->scale = cv_->DPIScale();
144+ if (top_layout_) top_layout_->scale = cv_->DPIScale();
145+ });
146+
147+ input_mixer_ = std::make_shared<InputMixer>();
148+ edge_borders_ = std::make_shared<EdgeBorders>(win_);
149+ edge_borders_->scale = cv_->DPIScale();
150+ input_mixer_->PushToFront(edge_borders_);
151+
152+ UpdateWindowEdgesGeo();
153+}
154+
155+void Window::Impl::UpdateWindowEdgesGeo()
156+{
157+ if (!edge_borders_)
158+ return;
159+
160+ auto const& input = win_->inputRect();
161+ edge_borders_->SetCoords(input.x(), input.y());
162+ edge_borders_->SetSize(input.width(), input.height());
163+}
164+
165+void Window::Impl::CleanupWindowEdges()
166+{
167+ input_mixer_.reset();
168+ edge_borders_.reset();
169+ dpi_changed_->disconnect();
170+}
171+
172 void Window::Impl::SetupWindowControls()
173 {
174 if (top_layout_)
175@@ -291,26 +364,7 @@
176 Decorate();
177 });
178
179- dpi_changed_ = Settings::Instance().dpi_changed.connect([this] {
180- Update();
181- top_layout_->scale = cv_->DPIScale();
182- });
183-
184- input_mixer_ = std::make_shared<InputMixer>();
185-
186- if (win_->actions() & CompWindowActionResizeMask)
187- {
188- auto edges = std::make_shared<EdgeBorders>(win_);
189- grab_edge_ = edges->GetEdge(Edge::Type::GRAB);
190- edge_borders_ = edges;
191- }
192- else /*if (win_->actions() & CompWindowActionMoveMask)*/
193- {
194- edge_borders_ = std::make_shared<GrabEdge>(win_);
195- grab_edge_ = edge_borders_;
196- }
197-
198- input_mixer_->PushToFront(edge_borders_);
199+ grab_edge_ = std::static_pointer_cast<EdgeBorders>(edge_borders_)->GetEdge(Edge::Type::GRAB);
200
201 auto padding = style->Padding(Side::TOP);
202 top_layout_ = std::make_shared<Layout>();
203@@ -345,6 +399,7 @@
204 top_layout_->Append(title_layout);
205
206 input_mixer_->PushToFront(top_layout_);
207+ dirty_frame_ = false;
208
209 SetupAppMenu();
210 RedrawDecorations();
211@@ -355,12 +410,12 @@
212 if (title_)
213 last_title_ = title_->text();
214
215+ if (input_mixer_)
216+ input_mixer_->Remove(top_layout_);
217+
218 UnsetAppMenu();
219 theme_changed_->disconnect();
220- dpi_changed_->disconnect();
221 top_layout_.reset();
222- input_mixer_.reset();
223- edge_borders_.reset();
224 }
225
226 bool Window::Impl::IsMaximized() const
227@@ -368,26 +423,25 @@
228 return (win_->state() & MAXIMIZE_STATE) == MAXIMIZE_STATE;
229 }
230
231+void Window::Impl::UpdateElements()
232+{
233+ if (!parent_->scaled() && IsMaximized())
234+ {
235+ deco_elements_ = cu::DecorationElement::NONE;
236+ return;
237+ }
238+
239+ deco_elements_ = cu::WindowDecorationElements(win_);
240+}
241+
242 bool Window::Impl::ShadowDecorated() const
243 {
244- if (!parent_->scaled() && IsMaximized())
245- return false;
246-
247- if (!cu::IsWindowShadowDecorable(win_))
248- return false;
249-
250- return true;
251+ return deco_elements_ & cu::DecorationElement::SHADOW;
252 }
253
254 bool Window::Impl::FullyDecorated() const
255 {
256- if (!parent_->scaled() && IsMaximized())
257- return false;
258-
259- if (!cu::IsWindowFullyDecorable(win_))
260- return false;
261-
262- return true;
263+ return deco_elements_ & cu::DecorationElement::BORDER;
264 }
265
266 bool Window::Impl::ShouldBeDecorated() const
267@@ -429,6 +483,7 @@
268 }
269
270 deco_tex.SetCoords(geo.x, geo.y);
271+ deco_tex.quad.region = deco_tex.quad.box;
272 }
273
274 void Window::Impl::UpdateDecorationTextures()
275@@ -440,7 +495,6 @@
276 }
277
278 auto const& geo = win_->borderRect();
279- auto const& input = win_->inputRect();
280 auto const& border = win_->border();
281
282 bg_textures_.resize(4);
283@@ -452,19 +506,18 @@
284 top_layout_->SetCoords(geo.x(), geo.y());
285 top_layout_->SetSize(geo.width(), border.top);
286
287- if (edge_borders_)
288- {
289- edge_borders_->SetCoords(input.x(), input.y());
290- edge_borders_->SetSize(input.width(), input.height());
291- }
292-
293 SyncMenusGeometries();
294 }
295
296 void Window::Impl::ComputeShadowQuads()
297 {
298- if (last_shadow_rect_.isEmpty() && !ShadowDecorated())
299+ if (!(deco_elements_ & cu::DecorationElement::SHADOW))
300+ {
301+ if (!last_shadow_rect_.isEmpty())
302+ last_shadow_rect_.setGeometry(0, 0, 0, 0);
303+
304 return;
305+ }
306
307 const auto* texture = ShadowTexture();
308
309@@ -552,6 +605,12 @@
310
311 if (shadows_rect != last_shadow_rect_)
312 {
313+ auto const& win_region = win_->region();
314+ quads[Quads::Pos::TOP_LEFT].region = CompRegion(quads[Quads::Pos::TOP_LEFT].box) - win_region;
315+ quads[Quads::Pos::TOP_RIGHT].region = CompRegion(quads[Quads::Pos::TOP_RIGHT].box) - win_region;
316+ quads[Quads::Pos::BOTTOM_LEFT].region = CompRegion(quads[Quads::Pos::BOTTOM_LEFT].box) - win_region;
317+ quads[Quads::Pos::BOTTOM_RIGHT].region = CompRegion(quads[Quads::Pos::BOTTOM_RIGHT].box) - win_region;
318+
319 last_shadow_rect_ = shadows_rect;
320 win_->updateWindowOutputExtents();
321 }
322@@ -561,15 +620,26 @@
323 GLWindowPaintAttrib const& attrib,
324 CompRegion const& region, unsigned mask)
325 {
326+ if (win_->defaultViewport() != screen->vp())
327+ return;
328+
329 if (dirty_geo_)
330 parent_->UpdateDecorationPosition();
331+
332+ if (dirty_frame_)
333+ {
334+ dirty_frame_ = false;
335+ CleanupWindowControls();
336+ CleanupWindowEdges();
337+ Update();
338+ }
339 }
340
341 void Window::Impl::Draw(GLMatrix const& transformation,
342 GLWindowPaintAttrib const& attrib,
343 CompRegion const& region, unsigned mask)
344 {
345- if (last_shadow_rect_.isEmpty())
346+ if (last_shadow_rect_.isEmpty() || win_->defaultViewport() != screen->vp())
347 return;
348
349 auto const& clip_region = (mask & PAINT_WINDOW_TRANSFORMED_MASK) ? infiniteRegion : region;
350@@ -580,7 +650,7 @@
351 for (unsigned i = 0; i < shadow_quads_.size(); ++i)
352 {
353 auto& quad = shadow_quads_[Quads::Pos(i)];
354- glwin_->glAddGeometry({quad.matrix}, CompRegion(quad.box) - win_->region(), clip_region);
355+ glwin_->glAddGeometry(quad.matrices, quad.region, clip_region);
356 }
357
358 if (glwin_->vertexBuffer()->end())
359@@ -592,7 +662,7 @@
360 continue;
361
362 glwin_->vertexBuffer()->begin();
363- glwin_->glAddGeometry({dtex.quad.matrix}, dtex.quad.box, clip_region);
364+ glwin_->glAddGeometry(dtex.quad.matrices, dtex.quad.region, clip_region);
365
366 if (glwin_->vertexBuffer()->end())
367 glwin_->glDrawTexture(dtex, transformation, attrib, mask);
368@@ -705,6 +775,9 @@
369
370 if (top_layout_)
371 top_layout_->scale = cv_->DPIScale();
372+
373+ if (edge_borders_)
374+ edge_borders_->scale = cv_->DPIScale();
375 }
376 }
377
378@@ -787,6 +860,7 @@
379 {
380 impl_->UpdateMonitor();
381 impl_->ComputeShadowQuads();
382+ impl_->UpdateWindowEdgesGeo();
383 impl_->UpdateDecorationTextures();
384 impl_->UpdateForceQuitDialogPosition();
385 impl_->dirty_geo_ = false;
386@@ -806,7 +880,8 @@
387 {
388 data.add(impl_->win_->borderRect())
389 .add("input_geo", impl_->win_->inputRect())
390- .add("content_geo", impl_->win_->region().boundingRect())
391+ .add("content_geo", impl_->win_->geometry())
392+ .add("region", impl_->win_->region().boundingRect())
393 .add("title", title())
394 .add("active", impl_->active())
395 .add("scaled", scaled())
396
397=== modified file 'decorations/DecorationsEdgeBorders.cpp'
398--- decorations/DecorationsEdgeBorders.cpp 2014-02-18 23:01:33 +0000
399+++ decorations/DecorationsEdgeBorders.cpp 2014-10-10 14:56:03 +0000
400@@ -26,21 +26,31 @@
401 {
402 namespace
403 {
404-const int MIN_CORNER_EDGE = 10;
405+const RawPixel MIN_CORNER_EDGE = 10_em;
406 }
407
408 EdgeBorders::EdgeBorders(CompWindow* win)
409 {
410- items_.resize(size_t(Edge::Type::Size));
411-
412- for (unsigned i = 0; i < unsigned(Edge::Type::Size); ++i)
413- {
414- auto type = Edge::Type(i);
415-
416- if (type == Edge::Type::GRAB)
417- items_[i] = std::make_shared<GrabEdge>(win);
418- else
419- items_[i] = std::make_shared<Edge>(win, type);
420+ scale.changed.connect(sigc::hide(sigc::mem_fun(this, &EdgeBorders::Relayout)));
421+
422+ if (win->actions() & CompWindowActionResizeMask)
423+ {
424+ items_.resize(size_t(Edge::Type::Size));
425+
426+ for (unsigned i = 0; i < unsigned(Edge::Type::Size); ++i)
427+ {
428+ auto type = Edge::Type(i);
429+
430+ if (type == Edge::Type::GRAB)
431+ items_[i] = std::make_shared<GrabEdge>(win);
432+ else
433+ items_[i] = std::make_shared<Edge>(win, type);
434+ }
435+ }
436+ else /*if (win->actions() & CompWindowActionMoveMask)*/
437+ {
438+ items_.resize(size_t(Edge::Type::GRAB) + 1);
439+ items_[unsigned(Edge::Type::GRAB)] = std::make_shared<GrabEdge>(win);
440 }
441
442 Relayout();
443@@ -54,10 +64,17 @@
444 auto const& ib = win->input();
445
446 using namespace compiz::window::extents;
447- Extents edges(std::max(ib.left, MIN_CORNER_EDGE),
448- std::max(ib.right, MIN_CORNER_EDGE),
449- std::max(ib.top, MIN_CORNER_EDGE),
450- std::max(ib.bottom, MIN_CORNER_EDGE));
451+ int min_corner_edge = MIN_CORNER_EDGE.CP(scale);
452+ Extents edges(std::max(ib.left, min_corner_edge),
453+ std::max(ib.right, min_corner_edge),
454+ std::max(ib.top, min_corner_edge),
455+ std::max(ib.bottom, min_corner_edge));
456+
457+ grab_edge->SetCoords(rect_.x() + ib.left, rect_.y() + ib.top - b.top);
458+ grab_edge->SetSize(rect_.width() - ib.left - ib.right, b.top);
459+
460+ if (items_.size() != size_t(Edge::Type::Size))
461+ return;
462
463 auto item = items_[unsigned(Edge::Type::TOP)];
464 item->SetCoords(rect_.x() + edges.left, rect_.y());
465@@ -90,10 +107,6 @@
466 item = items_[unsigned(Edge::Type::BOTTOM_RIGHT)];
467 item->SetCoords(rect_.x2() - edges.right, rect_.y2() - edges.bottom);
468 item->SetSize(edges.right, edges.bottom);
469-
470- item = items_[unsigned(Edge::Type::GRAB)];
471- item->SetCoords(rect_.x() + ib.left, rect_.y() + ib.top - b.top);
472- item->SetSize(rect_.width() - ib.left - ib.right, b.top);
473 }
474
475 Item::Ptr const& EdgeBorders::GetEdge(Edge::Type type) const
476
477=== modified file 'decorations/DecorationsForceQuitDialog.cpp'
478--- decorations/DecorationsForceQuitDialog.cpp 2014-06-13 15:23:12 +0000
479+++ decorations/DecorationsForceQuitDialog.cpp 2014-10-10 14:56:03 +0000
480@@ -141,7 +141,7 @@
481
482 auto const& deco_style = decoration::Style::Get();
483 auto const& offset = deco_style->ShadowOffset();
484- int max_offset = std::max(std::abs(offset.x), std::abs(offset.y));
485+ int max_offset = std::max(std::abs(offset.x * 4), std::abs(offset.y * 4));
486 gtk_container_set_border_width(GTK_CONTAINER(self), deco_style->ActiveShadowRadius()+max_offset);
487
488 auto* screen = gtk_window_get_screen(self);
489@@ -259,18 +259,32 @@
490 auto const& radius = deco_style->CornerRadius();
491 auto const& offset = deco_style->ShadowOffset();
492 auto const& color = deco_style->ActiveShadowColor();
493+ auto const& backcolor = deco_style->InactiveShadowColor();
494 int decoration_radius = std::max({radius.top, radius.left, radius.right, radius.bottom});
495
496- gtk_css_provider_load_from_data(style, (R"(SheetStyleDialog {
497+ gtk_css_provider_load_from_data(style, (R"(
498+ SheetStyleDialog {
499 background-color: #f7f6f5;
500 color: #4a4a4a;
501 border-radius: )"+std::to_string(decoration_radius)+R"(px;
502- box-shadow: )"+std::to_string(offset.x)+"px "+std::to_string(offset.y)+"px "+
503+ box-shadow: )"+std::to_string(2 * offset.x)+"px "+std::to_string(2 * offset.y)+"px "+
504 std::to_string(deco_style->ActiveShadowRadius())+"px "+
505 "rgba("+std::to_string(int(color.red * 255.0))+", "+
506 std::to_string(int(color.green * 255.0))+", "+
507 std::to_string(int(color.blue * 255.0))+", "+
508 std::to_string(int(color.alpha))+'.'+std::to_string(int(color.alpha*10000.0))+')'+R"(;
509+ }
510+
511+ SheetStyleDialog:backdrop {
512+ background-color: shade(#f7f6f5, 1.2);
513+ color: shade(#4a4a4a, 1.5);
514+ border-radius: )"+std::to_string(decoration_radius)+R"(px;
515+ box-shadow: )"+std::to_string(2 * offset.x)+"px "+std::to_string(2 * offset.y)+"px "+
516+ std::to_string(deco_style->InactiveShadowRadius())+"px "+
517+ "rgba("+std::to_string(int(backcolor.red * 255.0))+", "+
518+ std::to_string(int(backcolor.green * 255.0))+", "+
519+ std::to_string(int(backcolor.blue * 255.0))+", "+
520+ std::to_string(int(backcolor.alpha))+'.'+std::to_string(int(backcolor.alpha*10000.0))+')'+R"(;
521 })").c_str(), -1, nullptr);
522
523 auto* style_ctx = gtk_widget_get_style_context(self);
524
525=== modified file 'decorations/DecorationsManager.cpp'
526--- decorations/DecorationsManager.cpp 2014-07-30 00:49:35 +0000
527+++ decorations/DecorationsManager.cpp 2014-10-10 14:56:03 +0000
528@@ -41,8 +41,7 @@
529 }
530
531 Manager::Impl::Impl(decoration::Manager* parent, menu::Manager::Ptr const& menu)
532- : active_window_(0)
533- , enable_add_supported_atoms_(true)
534+ : enable_add_supported_atoms_(true)
535 , data_pool_(DataPool::Get())
536 , menu_manager_(menu)
537 {
538@@ -52,7 +51,6 @@
539 Display* dpy = screen->dpy();
540 atom::_NET_REQUEST_FRAME_EXTENTS = XInternAtom(dpy, "_NET_REQUEST_FRAME_EXTENTS", False);
541 atom::_NET_WM_VISIBLE_NAME = XInternAtom(dpy, "_NET_WM_VISIBLE_NAME", False);
542- screen->updateSupportedWmHints();
543
544 auto rebuild_cb = sigc::mem_fun(this, &Impl::OnShadowOptionsChanged);
545 manager_->active_shadow_color.changed.connect(sigc::hide(sigc::bind(rebuild_cb, true)));
546@@ -205,8 +203,6 @@
547
548 bool Manager::Impl::HandleEventBefore(XEvent* event)
549 {
550- active_window_ = screen->activeWindow();
551-
552 switch (event->type)
553 {
554 case ClientMessage:
555@@ -251,31 +247,26 @@
556
557 bool Manager::Impl::HandleEventAfter(XEvent* event)
558 {
559- if (screen->activeWindow() != active_window_)
560- {
561- // Do this when _NET_ACTIVE_WINDOW changes on root!
562- if (active_deco_win_)
563- active_deco_win_->impl_->active = false;
564-
565- active_window_ = screen->activeWindow();
566- auto const& new_active = GetWindowByXid(active_window_);
567- active_deco_win_ = new_active;
568-
569- if (new_active)
570- new_active->impl_->active = true;
571- }
572-
573 switch (event->type)
574 {
575 case PropertyNotify:
576 {
577- if (event->xproperty.atom == Atoms::mwmHints)
578+ if (event->xproperty.atom == Atoms::winActive)
579+ {
580+ if (active_deco_win_)
581+ active_deco_win_->impl_->active = false;
582+
583+ auto const& new_active = GetWindowByXid(screen->activeWindow());
584+ active_deco_win_ = new_active;
585+
586+ if (new_active)
587+ new_active->impl_->active = true;
588+ }
589+ else if (event->xproperty.atom == Atoms::mwmHints ||
590+ event->xproperty.atom == Atoms::wmAllowedActions)
591 {
592 if (Window::Ptr const& win = GetWindowByXid(event->xproperty.window))
593- {
594- win->impl_->CleanupWindowControls();
595- win->Update();
596- }
597+ win->impl_->UpdateFrameActions();
598 }
599 else if (event->xproperty.atom == XA_WM_NAME ||
600 event->xproperty.atom == Atoms::wmName ||
601@@ -442,7 +433,7 @@
602 .add("active_shadow_radius", active_shadow_radius())
603 .add("inactive_shadow_color", inactive_shadow_color())
604 .add("inactive_shadow_radius", inactive_shadow_radius())
605- .add("active_window", impl_->active_window_);
606+ .add("active_window", screen->activeWindow());
607 }
608
609 debug::Introspectable::IntrospectableList Manager::GetIntrospectableChildren()
610
611=== modified file 'decorations/DecorationsPriv.h'
612--- decorations/DecorationsPriv.h 2014-04-02 09:05:59 +0000
613+++ decorations/DecorationsPriv.h 2014-10-10 14:56:03 +0000
614@@ -1,6 +1,6 @@
615 // -*- Mode: C++; indent-tabs-mode: nil; tab-width: 2 -*-
616 /*
617- * Copyright (C) 2013 Canonical Ltd
618+ * Copyright (C) 2013-2014 Canonical Ltd
619 *
620 * This program is free software: you can redistribute it and/or modify
621 * it under the terms of the GNU General Public License version 3 as
622@@ -92,11 +92,15 @@
623 private:
624 void UnsetExtents();
625 void SetupExtents();
626+ void UpdateElements();
627 void UpdateMonitor();
628 void UpdateFrame();
629 void CreateFrame(nux::Geometry const&);
630 void UpdateFrameGeo(nux::Geometry const&);
631+ void UpdateFrameActions();
632 void UnsetFrame();
633+ void SetupWindowEdges();
634+ void CleanupWindowEdges();
635 void SetupWindowControls();
636 void CleanupWindowControls();
637 void UnsetAppMenu();
638@@ -109,6 +113,7 @@
639
640 void ComputeShadowQuads();
641 void UpdateDecorationTextures();
642+ void UpdateWindowEdgesGeo();
643 void UpdateForceQuitDialogPosition();
644 void RenderDecorationTexture(Side, nux::Geometry const&);
645 void Paint(GLMatrix const&, GLWindowPaintAttrib const&, CompRegion const&, unsigned mask);
646@@ -122,8 +127,12 @@
647 ::CompositeWindow* cwin_;
648 ::GLWindow* glwin_;
649 ::Window frame_;
650+ int monitor_;
651 bool dirty_geo_;
652- int monitor_;
653+ bool dirty_frame_;
654+ unsigned deco_elements_;
655+ unsigned last_mwm_decor_;
656+ unsigned last_actions_;
657
658 CompRect last_shadow_rect_;
659 Quads shadow_quads_;
660@@ -176,7 +185,6 @@
661 friend class Manager;
662 friend struct Window::Impl;
663
664- ::Window active_window_;
665 bool enable_add_supported_atoms_;
666
667 DataPool::Ptr data_pool_;
668
669=== modified file 'decorations/DecorationsTitle.cpp'
670--- decorations/DecorationsTitle.cpp 2014-03-31 18:36:07 +0000
671+++ decorations/DecorationsTitle.cpp 2014-10-10 14:56:03 +0000
672@@ -80,6 +80,7 @@
673
674 Style::Get()->DrawTitle(text(), state, text_ctx, texture_size_.width / scale(), texture_size_.height / scale(), bg_geo * (1.0/scale));
675 SetTexture(text_ctx);
676+ texture_.UpdateMatrix();
677 }
678
679 void Title::SetX(int x)
680
681=== modified file 'decorations/DecorationsWidgets.cpp'
682--- decorations/DecorationsWidgets.cpp 2014-02-27 07:10:31 +0000
683+++ decorations/DecorationsWidgets.cpp 2014-10-10 14:56:03 +0000
684@@ -226,6 +226,12 @@
685
686 //
687
688+TexturedItem::TexturedItem()
689+ : dirty_region_(false)
690+{
691+ geo_parameters_changed.connect([this] { dirty_region_ = true; });
692+}
693+
694 void TexturedItem::SetTexture(cu::SimpleTexture::Ptr const& tex)
695 {
696 auto prev_geo = Geometry();
697@@ -254,8 +260,14 @@
698 if (!visible || Geometry().isEmpty() || !texture_)
699 return;
700
701+ if (dirty_region_)
702+ {
703+ texture_.quad.region = texture_.quad.box;
704+ dirty_region_ = false;
705+ }
706+
707 ctx->vertexBuffer()->begin();
708- ctx->glAddGeometry({texture_.quad.matrix}, texture_.quad.box, clip);
709+ ctx->glAddGeometry(texture_.quad.matrices, texture_.quad.region, clip);
710
711 if (ctx->vertexBuffer()->end())
712 ctx->glDrawTexture(texture_, transformation, attrib, mask);
713
714=== modified file 'decorations/DecorationsWidgets.h'
715--- decorations/DecorationsWidgets.h 2014-02-27 07:10:31 +0000
716+++ decorations/DecorationsWidgets.h 2014-10-10 14:56:03 +0000
717@@ -121,6 +121,8 @@
718 public:
719 typedef std::shared_ptr<TexturedItem> Ptr;
720
721+ TexturedItem();
722+
723 void SetTexture(cu::SimpleTexture::Ptr const&);
724 void Draw(GLWindow*, GLMatrix const&, GLWindowPaintAttrib const&, CompRegion const&, unsigned mask);
725 void SetCoords(int x, int y);
726@@ -133,6 +135,9 @@
727
728 CompRect& InternalGeo();
729 cu::SimpleTextureQuad texture_;
730+
731+private:
732+ bool dirty_region_;
733 };
734
735
736
737=== modified file 'plugins/unityshell/src/unityshell.cpp'
738--- plugins/unityshell/src/unityshell.cpp 2014-09-04 22:12:01 +0000
739+++ plugins/unityshell/src/unityshell.cpp 2014-10-10 14:56:03 +0000
740@@ -281,6 +281,7 @@
741 CompositeScreenInterface::setHandler(cScreen);
742 GLScreenInterface::setHandler(gScreen);
743 ScaleScreenInterface::setHandler(sScreen);
744+ screen->updateSupportedWmHints();
745
746 PluginAdapter::Initialize(screen);
747 AddChild(&WindowManager::Default());
748
749=== modified file 'unity-shared/CompizUtils.cpp'
750--- unity-shared/CompizUtils.cpp 2014-04-14 13:51:58 +0000
751+++ unity-shared/CompizUtils.cpp 2014-10-10 14:56:03 +0000
752@@ -1,6 +1,6 @@
753 // -*- Mode: C++; indent-tabs-mode: nil; tab-width: 2 -*-
754 /*
755-* Copyright (C) 2013 Canonical Ltd
756+* Copyright (C) 2013-2014 Canonical Ltd
757 *
758 * This program is free software: you can redistribute it and/or modify
759 * it under the terms of the GNU General Public License version 3 as
760@@ -30,6 +30,11 @@
761 {
762 const unsigned PIXMAP_DEPTH = 32;
763 const float DEFAULT_SCALE = 1.0f;
764+ const unsigned DECORABLE_WINDOW_TYPES = CompWindowTypeDialogMask |
765+ CompWindowTypeModalDialogMask |
766+ CompWindowTypeUtilMask |
767+ CompWindowTypeMenuMask |
768+ CompWindowTypeNormalMask;
769 }
770
771 SimpleTexture::SimpleTexture(GLTexture::List const& tex)
772@@ -39,7 +44,7 @@
773 //
774
775 SimpleTextureQuad::SimpleTextureQuad()
776- : scale(DEFAULT_SCALE)
777+ : scale_(DEFAULT_SCALE)
778 {}
779
780 bool SimpleTextureQuad::SetTexture(SimpleTexture::Ptr const& simple_texture)
781@@ -52,24 +57,27 @@
782 if (st && st->texture())
783 {
784 auto* tex = st->texture();
785- CompPoint old_coords(quad.box.x(), quad.box.y());
786- short invalid = std::numeric_limits<short>::min();
787- quad.box.setGeometry(invalid, invalid, tex->width() * scale, tex->height() * scale);
788- SetCoords(old_coords.x(), old_coords.y());
789+ CompSize size(tex->width() * scale_, tex->height() * scale_);
790+
791+ if (quad.box.width() != size.width() || quad.box.height() != size.height())
792+ {
793+ quad.box.setSize(size);
794+ UpdateMatrix();
795+ }
796 }
797
798 return true;
799 }
800
801-bool SimpleTextureQuad::SetScale(float s)
802+bool SimpleTextureQuad::SetScale(double s)
803 {
804- if (!st || scale == s)
805+ if (!st || scale_ == s)
806 return false;
807
808- scale = s;
809+ scale_ = s;
810 auto* tex = st->texture();
811- quad.box.setWidth(tex->width() * scale);
812- quad.box.setHeight(tex->height() * scale);
813+ quad.box.setWidth(tex->width() * scale_);
814+ quad.box.setHeight(tex->height() * scale_);
815 UpdateMatrix();
816 return true;
817 }
818@@ -91,8 +99,8 @@
819 int y = quad.box.y();
820
821 quad.matrix = (st && st->texture()) ? st->texture()->matrix() : GLTexture::Matrix();
822- quad.matrix.xx /= scale;
823- quad.matrix.yy /= scale;
824+ quad.matrix.xx /= scale_;
825+ quad.matrix.yy /= scale_;
826 quad.matrix.x0 = 0.0f - COMP_TEX_COORD_X(quad.matrix, x);
827 quad.matrix.y0 = 0.0f - COMP_TEX_COORD_Y(quad.matrix, y);
828 }
829@@ -166,57 +174,68 @@
830 return cairo_xlib_surface_get_height(surface_);
831 }
832
833-bool IsWindowShadowDecorable(CompWindow* win)
834+//
835+//
836+
837+unsigned WindowDecorationElements(CompWindow* win)
838 {
839+ unsigned elements = DecorationElement::NONE;
840+
841 if (!win)
842- return false;
843+ return elements;
844
845 if (!win->isViewable())
846- return false;
847+ return elements;
848
849 if (win->wmType() & (CompWindowTypeDockMask | CompWindowTypeDesktopMask))
850- return false;
851-
852- if (win->region().numRects() != 1) // Non rectangular windows
853- return false;
854-
855- if (win->alpha())
856- return WindowHasMotifDecorations(win);
857-
858- return true;
859+ return elements;
860+
861+ if (win->inShowDesktopMode())
862+ return elements;
863+
864+ auto const& region = win->region();
865+ bool rectangular = (region.numRects() == 1);
866+ bool alpha = win->alpha();
867+
868+ if (!rectangular && alpha) // Non-rectangular windows with alpha channel
869+ return elements;
870+
871+ if (region.boundingRect() != win->geometry()) // Shaped windows
872+ return elements;
873+
874+ if (rectangular)
875+ elements |= DecorationElement::SHADOW;
876+
877+ if (!win->overrideRedirect() &&
878+ (win->type() & DECORABLE_WINDOW_TYPES) &&
879+ (win->frame() || win->hasUnmapReference()))
880+ {
881+ if (win->actions() & CompWindowActionResizeMask)
882+ elements |= DecorationElement::EDGE;
883+
884+ if (rectangular && (win->mwmDecor() & (MwmDecorAll | MwmDecorTitle)))
885+ elements |= DecorationElement::BORDER;
886+ }
887+
888+ if (alpha && !(elements & DecorationElement::BORDER) && !(win->mwmDecor() & MwmDecorBorder))
889+ elements &= ~DecorationElement::SHADOW;
890+
891+ return elements;
892+}
893+
894+bool IsWindowEdgeDecorable(CompWindow* win)
895+{
896+ return WindowDecorationElements(win) & DecorationElement::EDGE;
897+}
898+
899+bool IsWindowShadowDecorable(CompWindow* win)
900+{
901+ return WindowDecorationElements(win) & DecorationElement::SHADOW;
902 }
903
904 bool IsWindowFullyDecorable(CompWindow* win)
905 {
906- if (!win)
907- return false;
908-
909- if (!IsWindowShadowDecorable(win))
910- return false;
911-
912- return WindowHasMotifDecorations(win);
913-}
914-
915-bool WindowHasMotifDecorations(CompWindow* win)
916-{
917- if (!win)
918- return false;
919-
920- if (win->overrideRedirect())
921- return false;
922-
923- switch (win->type())
924- {
925- case CompWindowTypeDialogMask:
926- case CompWindowTypeModalDialogMask:
927- case CompWindowTypeUtilMask:
928- case CompWindowTypeMenuMask:
929- case CompWindowTypeNormalMask:
930- if (win->mwmDecor() & (MwmDecorAll | MwmDecorTitle))
931- return true;
932- }
933-
934- return false;
935+ return WindowDecorationElements(win) & DecorationElement::BORDER;
936 }
937
938 } // compiz_utils namespace
939
940=== modified file 'unity-shared/CompizUtils.h'
941--- unity-shared/CompizUtils.h 2014-04-14 13:51:58 +0000
942+++ unity-shared/CompizUtils.h 2014-10-10 14:56:03 +0000
943@@ -31,8 +31,15 @@
944
945 struct TextureQuad
946 {
947+ TextureQuad()
948+ : matrices(1)
949+ , matrix(matrices[0])
950+ {}
951+
952 CompRect box;
953- GLTexture::Matrix matrix;
954+ CompRegion region;
955+ GLTexture::MatrixList matrices;
956+ GLTexture::Matrix& matrix;
957 };
958
959 struct SimpleTexture
960@@ -59,11 +66,13 @@
961 {
962 SimpleTextureQuad();
963 bool SetTexture(SimpleTexture::Ptr const&);
964- bool SetScale(float scale);
965+ bool SetScale(double scale);
966 bool SetCoords(int x, int y);
967 bool SetX(int x);
968 bool SetY(int y);
969
970+ void UpdateMatrix();
971+
972 operator SimpleTexture::Ptr() const { return st; }
973 operator bool() const { return st && st->texture(); }
974 operator GLTexture*() const { return st ? st->texture() : nullptr; }
975@@ -73,8 +82,7 @@
976 TextureQuad quad;
977
978 private:
979- void UpdateMatrix();
980- float scale;
981+ double scale_;
982 };
983
984 struct PixmapTexture : SimpleTexture
985@@ -111,9 +119,20 @@
986 cairo_t *cr_;
987 };
988
989+enum DecorationElement
990+{
991+ NONE = 0,
992+ EDGE = (1 << 0),
993+ SHADOW = (1 << 1),
994+ BORDER = (1 << 2),
995+ FULL = EDGE|SHADOW|BORDER
996+};
997+
998+unsigned WindowDecorationElements(CompWindow*);
999+
1000+bool IsWindowEdgeDecorable(CompWindow*);
1001 bool IsWindowShadowDecorable(CompWindow*);
1002 bool IsWindowFullyDecorable(CompWindow*);
1003-bool WindowHasMotifDecorations(CompWindow*);
1004
1005 } // compiz_utils namespace
1006 } // unity namespace
1007
1008=== modified file 'unity-shared/XWindowManager.cpp'
1009--- unity-shared/XWindowManager.cpp 2014-02-14 03:05:02 +0000
1010+++ unity-shared/XWindowManager.cpp 2014-10-10 14:56:03 +0000
1011@@ -83,7 +83,7 @@
1012 {
1013 LOG_ERROR(logger) << "Impossible to get the property " << gdk_x11_get_xatom_name(atom)
1014 << " for window " << window_id << ": invalid string type: "
1015- << gdk_x11_get_xatom_name(Atoms::utf8String);
1016+ << gdk_x11_get_xatom_name(type);
1017 return std::string();
1018 }
1019