diff options
67 files changed, 1261 insertions, 403 deletions
diff --git a/dash/DashController.cpp b/dash/DashController.cpp index b4d63dd3a..d1acc8df6 100644 --- a/dash/DashController.cpp +++ b/dash/DashController.cpp @@ -195,6 +195,11 @@ void Controller::EnsureDash() } } +int Controller::Monitor() const +{ + return monitor_; +} + nux::BaseWindow* Controller::window() const { return window_.GetPointer(); @@ -299,7 +304,7 @@ void Controller::ShowDash() monitor_ = GetIdealMonitor(); int launcher_width = unity::Settings::Instance().LauncherWidth(monitor_); view_->SetMonitorOffset(launcher_width, panel::Style::Instance().PanelHeight(monitor_)); - view_->AboutToShow(); + view_->AboutToShow(monitor_); FocusWindow(); need_show_ = false; diff --git a/dash/DashController.h b/dash/DashController.h index 904a8e9ab..5705d38da 100644 --- a/dash/DashController.h +++ b/dash/DashController.h @@ -68,6 +68,8 @@ public: bool IsCommandLensOpen() const; nux::Geometry GetInputWindowGeometry(); nux::ObjectPtr<DashView> const& Dash() const; + + int Monitor() const; protected: std::string GetName() const; diff --git a/dash/DashView.cpp b/dash/DashView.cpp index 3870dd0a6..89e7717e8 100644 --- a/dash/DashView.cpp +++ b/dash/DashView.cpp @@ -1,5 +1,5 @@ /* - * Copyright (C) 2010 Canonical Ltd + * Copyright (C) 2010-2014 Canonical Ltd * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License version 3 as @@ -36,6 +36,7 @@ #include "unity-shared/DashStyle.h" #include "unity-shared/KeyboardUtil.h" #include "unity-shared/PreviewStyle.h" +#include "unity-shared/RawPixel.h" #include "unity-shared/UBusMessages.h" #include "unity-shared/UnitySettings.h" #include "unity-shared/WindowManager.h" @@ -53,10 +54,9 @@ const int PREVIEW_ANIMATION_LENGTH = 250; const int DASH_TILE_HORIZONTAL_COUNT = 6; const int DASH_DEFAULT_CATEGORY_COUNT = 3; -const int DASH_RESULT_RIGHT_PAD = 35; -const int GROUP_HEADING_HEIGHT = 24; -const int PREVIEW_ICON_SPLIT_OFFSCREEN_OFFSET = 10; +const RawPixel DASH_RESULT_RIGHT_PAD = 35_em; +const RawPixel PREVIEW_ICON_SPLIT_OFFSCREEN_OFFSET = 10_em; const int MAX_ENTRY_ACTIVATE_WAIT_TIMEOUT = 1000; } @@ -129,6 +129,8 @@ DashView::DashView(Scopes::Ptr const& scopes, ApplicationStarter::Ptr const& app , animate_preview_container_value_(0.0) , animate_preview_value_(0.0) , overlay_window_buttons_(new OverlayWindowButtons()) + , cv_(Settings::Instance().em()) + , monitor_(0) { renderer_.SetOwner(this); renderer_.need_redraw.connect([this] () { @@ -155,6 +157,8 @@ DashView::DashView(Scopes::Ptr const& scopes, ApplicationStarter::Ptr const& app if (visible_ && !area) nux::GetWindowCompositor().SetKeyFocusArea(default_focus()); }); + + unity::Settings::Instance().dpi_changed.connect(sigc::mem_fun(this, &DashView::OnDPIChanged)); } DashView::~DashView() @@ -454,11 +458,20 @@ void DashView::OnPreviewAnimationFinished() content_view_->SetPresentRedirectedView(true); } -void DashView::AboutToShow() +void DashView::AboutToShow(int monitor) { visible_ = true; search_bar_->text_entry()->SelectAll(); + if (monitor_ != monitor) + { + monitor_ = monitor; + cv_ = Settings::Instance().em(monitor_); + + OnDPIChanged(); + Relayout(); + } + /* Give the scopes a chance to prep data before we map them */ if (active_scope_view_) { @@ -518,31 +531,24 @@ void DashView::AboutToHide() void DashView::SetupViews() { - dash::Style& style = dash::Style::Instance(); - layout_ = new nux::VLayout(); - layout_->SetLeftAndRightPadding(style.GetVSeparatorSize(), 0); - layout_->SetTopAndBottomPadding(style.GetHSeparatorSize(), 0); SetLayout(layout_); top_space_ = new nux::SpaceLayout(0, 0, renderer_.y_offset(), renderer_.y_offset()); layout_->AddLayout(top_space_, 0); content_layout_ = new DashLayout(NUX_TRACKER_LOCATION); - content_layout_->SetTopAndBottomPadding(style.GetDashViewTopPadding(), 0); content_view_ = new DashContentView(NUX_TRACKER_LOCATION); content_view_->SetLayout(content_layout_); layout_->AddView(content_view_, 1, nux::MINOR_POSITION_START, nux::MINOR_SIZE_FULL); search_bar_layout_ = new nux::HLayout(); - search_bar_layout_->SetLeftAndRightPadding(style.GetSearchBarLeftPadding(), 0); content_layout_->AddLayout(search_bar_layout_, 0, nux::MINOR_POSITION_CENTER, nux::MINOR_SIZE_FULL); search_bar_ = new SearchBar(true); + search_bar_->UpdateScale(cv_->DPIScale()); AddChild(search_bar_); - search_bar_->SetMinimumHeight(style.GetSearchBarHeight()); - search_bar_->SetMaximumHeight(style.GetSearchBarHeight()); search_bar_->activated.connect(sigc::mem_fun(this, &DashView::OnEntryActivated)); search_bar_->search_changed.connect(sigc::mem_fun(this, &DashView::OnSearchChanged)); search_bar_->live_search_reached.connect(sigc::mem_fun(this, &DashView::OnLiveSearchReached)); @@ -564,6 +570,42 @@ void DashView::SetupViews() AddChild(scope_bar_); scope_bar_->scope_activated.connect(sigc::mem_fun(this, &DashView::OnScopeBarActivated)); content_layout_->AddView(scope_bar_, 0, nux::MINOR_POSITION_CENTER); + + UpdateDashViewSize(); +} + +void DashView::OnDPIChanged() +{ + double scale = cv_->DPIScale(); + + UpdateDashViewSize(); + + for (auto& scope : scope_views_) + scope.second->UpdateScale(scale); + + search_bar_->UpdateScale(scale); + scope_bar_->UpdateScale(cv_->DPIScale()); +} + +void DashView::UpdateDashViewSize() +{ + dash::Style const& style = dash::Style::Instance(); + + RawPixel const v_separator_size = style.GetVSeparatorSize(); + RawPixel const h_separator_size = style.GetHSeparatorSize(); + RawPixel const view_top_padding = style.GetDashViewTopPadding(); + + RawPixel const search_bar_left_padding = style.GetSearchBarLeftPadding(); + RawPixel const search_bar_height = style.GetSearchBarHeight(); + + layout_->SetLeftAndRightPadding(v_separator_size.CP(cv_), 0); + layout_->SetTopAndBottomPadding(h_separator_size.CP(cv_), 0); + + content_layout_->SetTopAndBottomPadding(view_top_padding.CP(cv_), 0); + + search_bar_layout_->SetLeftAndRightPadding(search_bar_left_padding.CP(cv_), 0); + search_bar_->SetMinimumHeight(search_bar_height.CP(cv_)); + search_bar_->SetMaximumHeight(search_bar_height.CP(cv_)); } void DashView::SetupUBusConnections() @@ -584,17 +626,26 @@ void DashView::Relayout() content_geo_ = GetBestFitGeometry(geo); dash::Style& style = dash::Style::Instance(); + RawPixel const top_padding = style.GetDashViewTopPadding(); + // kinda hacky, but it makes sure the content isn't so big that it throws // the bottom of the dash off the screen // not hugely happy with this, so FIXME - scopes_layout_->SetMaximumHeight (std::max(0, content_geo_.height - search_bar_->GetGeometry().height - scope_bar_->GetGeometry().height - style.GetDashViewTopPadding())); - scopes_layout_->SetMinimumHeight (std::max(0, content_geo_.height - search_bar_->GetGeometry().height - scope_bar_->GetGeometry().height - style.GetDashViewTopPadding())); + scopes_layout_->SetMaximumHeight (std::max(0, content_geo_.height - + search_bar_->GetGeometry().height - + scope_bar_->GetGeometry().height - + top_padding.CP(cv_))); + + scopes_layout_->SetMinimumHeight (std::max(0, content_geo_.height - + search_bar_->GetGeometry().height - + scope_bar_->GetGeometry().height - + top_padding.CP(cv_))); layout_->SetMinMaxSize(content_geo_.width, content_geo_.y + content_geo_.height); // Minus the padding that gets added to the left - float tile_width = style.GetTileWidth(); - style.SetDefaultNColumns(floorf((content_geo_.width - 32) / tile_width)); + RawPixel const tile_width = style.GetTileWidth(); + style.SetDefaultNColumns(floorf((content_geo_.width - cv_->CP(32)) / tile_width.CP(cv_))); ubus_manager_.SendMessage(UBUS_DASH_SIZE_CHANGED, g_variant_new("(ii)", content_geo_.width, content_geo_.height)); @@ -615,22 +666,33 @@ nux::Geometry DashView::GetBestFitGeometry(nux::Geometry const& for_geo) int panel_height = renderer_.y_offset; int width = 0, height = 0; - int tile_width = style.GetTileWidth(); - int tile_height = style.GetTileHeight(); - int category_height = (style.GetPlacesGroupTopSpace() + style.GetCategoryIconSize() + style.GetPlacesGroupResultTopPadding() + tile_height); + RawPixel const tile_width = style.GetTileWidth(); + RawPixel const tile_height = style.GetTileHeight(); + RawPixel const group_top_space = style.GetPlacesGroupTopSpace(); + RawPixel const category_icon_size = style.GetCategoryIconSize(); + RawPixel const group_top_padding = style.GetPlacesGroupResultTopPadding(); + + int category_height = (group_top_space.CP(cv_) + category_icon_size.CP(cv_) + + group_top_padding.CP(cv_) + tile_height.CP(cv_)); + int half = for_geo.width / 2; // if default dash size is bigger than half a screens worth of items, go for that. - while ((width += tile_width) < half) + while ((width += tile_width.CP(cv_)) < half) ; - width = std::max(width, tile_width * DASH_TILE_HORIZONTAL_COUNT); - width += style.GetVSeparatorSize(); - width += style.GetPlacesGroupResultLeftPadding() + DASH_RESULT_RIGHT_PAD; + RawPixel const v_separator_size = style.GetVSeparatorSize(); + RawPixel const group_left_padding = style.GetPlacesGroupResultLeftPadding(); + + width = std::max(width, tile_width.CP(cv_) * DASH_TILE_HORIZONTAL_COUNT); + width += v_separator_size.CP(cv_); + width += group_left_padding.CP(cv_) + DASH_RESULT_RIGHT_PAD.CP(cv_); + RawPixel const h_separator_size = style.GetHSeparatorSize(); + RawPixel const top_padding = style.GetDashViewTopPadding(); - height = style.GetHSeparatorSize(); - height += style.GetDashViewTopPadding(); + height = h_separator_size.CP(cv_); + height += top_padding.CP(cv_); height += search_bar_->GetGeometry().height; height += category_height * DASH_DEFAULT_CATEGORY_COUNT; // adding three categories height += scope_bar_->GetGeometry().height; @@ -744,7 +806,7 @@ void DashView::DrawDashSplit(nux::GraphicsEngine& graphics_engine, nux::Geometry texxform.voffset = (scope_bar_->GetY() - content_view_->GetY())/(float)content_view_->GetHeight(); int start_y = scope_bar_->GetY(); - int final_y = geo_layout.y + geo_layout.height + PREVIEW_ICON_SPLIT_OFFSCREEN_OFFSET; + int final_y = geo_layout.y + geo_layout.height + PREVIEW_ICON_SPLIT_OFFSCREEN_OFFSET.CP(cv_); int scope_y = (1.0f - animate_split_value_) * start_y + (animate_split_value_ * final_y); @@ -768,7 +830,7 @@ void DashView::DrawDashSplit(nux::GraphicsEngine& graphics_engine, nux::Geometry texxform.voffset = (search_bar_->GetY() - content_view_->GetY())/(float)content_view_->GetHeight(); start_y = search_bar_->GetY(); - final_y = geo_layout.y - search_bar_->GetHeight() - PREVIEW_ICON_SPLIT_OFFSCREEN_OFFSET; + final_y = geo_layout.y - search_bar_->GetHeight() - PREVIEW_ICON_SPLIT_OFFSCREEN_OFFSET.CP(cv_); graphics_engine.QRP_1Tex ( @@ -786,7 +848,7 @@ void DashView::DrawDashSplit(nux::GraphicsEngine& graphics_engine, nux::Geometry texxform.voffset = (search_bar_->GetY() - content_view_->GetY())/(float)content_view_->GetHeight(); int start_x = active_scope_view_->filter_bar()->GetX(); - int final_x = content_view_->GetX() + content_view_->GetWidth() + PREVIEW_ICON_SPLIT_OFFSCREEN_OFFSET; + int final_x = content_view_->GetX() + content_view_->GetWidth() + PREVIEW_ICON_SPLIT_OFFSCREEN_OFFSET.CP(cv_); int filter_x = (1.0f - animate_split_value_) * start_x + (animate_split_value_ * final_x); @@ -810,7 +872,7 @@ void DashView::DrawDashSplit(nux::GraphicsEngine& graphics_engine, nux::Geometry texxform.voffset = (search_bar_->GetY() - content_view_->GetY())/(float)content_view_->GetHeight(); int start_y = search_bar_->GetY(); - int final_y = geo_layout.y - search_bar_->GetHeight() - PREVIEW_ICON_SPLIT_OFFSCREEN_OFFSET; + int final_y = geo_layout.y - search_bar_->GetHeight() - PREVIEW_ICON_SPLIT_OFFSCREEN_OFFSET.CP(cv_); graphics_engine.QRP_1Tex ( @@ -844,8 +906,8 @@ void DashView::DrawPreviewContainer(nux::GraphicsEngine& graphics_engine) // Triangle pointed at preview item if (opening_column_x_ != -1) { - int final_width = 14; - int final_height = 12; + int final_width = cv_->CP(14); + int final_height = cv_->CP(12); int x_center = geo_content.x + (opening_column_x_ - geo_abs.x) + opening_column_width_ / 2; int start_y = geo_abs_preview.y - geo_abs.y; @@ -1069,13 +1131,16 @@ void DashView::DrawPreview(nux::GraphicsEngine& graphics_engine, bool force_draw void DashView::OnMouseButtonDown(int x, int y, unsigned long button, unsigned long key) { - dash::Style& style = dash::Style::Instance(); nux::Geometry geo(content_geo_); if (Settings::Instance().form_factor() == FormFactor::DESKTOP) { - geo.width += style.GetDashRightTileWidth(); - geo.height += style.GetDashBottomTileHeight(); + dash::Style& style = dash::Style::Instance(); + RawPixel const right_title_width = style.GetDashRightTileWidth(); + RawPixel const bottom_title_width = style.GetDashBottomTileHeight(); + + geo.width += right_title_width.CP(cv_); + geo.height += bottom_title_width.CP(cv_); } } @@ -1217,6 +1282,7 @@ void DashView::OnScopeAdded(Scope::Ptr const& scope, int position) nux::ObjectPtr<ScopeView> view(new ScopeView(scope, search_bar_->show_filters())); AddChild(view.GetPointer()); + view->UpdateScale(cv_->DPIScale()); view->SetVisible(false); view->result_activated.connect(sigc::mem_fun(this, &DashView::OnResultActivated)); @@ -1434,6 +1500,9 @@ void DashView::AddProperties(debug::IntrospectionData& introspection) int num_rows = 1; // The search bar std::vector<bool> button_on_monitor; + RawPixel const right_title_width = style.GetDashRightTileWidth(); + RawPixel const bottom_title_width = style.GetDashBottomTileHeight(); + if (active_scope_view_.IsValid()) num_rows += active_scope_view_->GetNumRows(); @@ -1452,8 +1521,8 @@ void DashView::AddProperties(debug::IntrospectionData& introspection) introspection.add(nux::Geometry(GetAbsoluteX(), GetAbsoluteY(), content_geo_.width, content_geo_.height)) .add("num_rows", num_rows) .add("form_factor", form_factor) - .add("right-border-width", style.GetDashRightTileWidth()) - .add("bottom-border-height", style.GetDashBottomTileHeight()) + .add("right-border-width", right_title_width.CP(cv_)) + .add("bottom-border-height", bottom_title_width.CP(cv_)) .add("preview_displaying", preview_displaying_) .add("preview_animation", animate_split_value_ * animate_preview_container_value_ * animate_preview_value_) .add("dash_maximized", style.always_maximised()) diff --git a/dash/DashView.h b/dash/DashView.h index 6b94cb864..e60f6a1c7 100644 --- a/dash/DashView.h +++ b/dash/DashView.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2010 Canonical Ltd + * Copyright (C) 2010-2014 Canonical Ltd * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License version 3 as @@ -37,6 +37,7 @@ #include "unity-shared/BackgroundEffectHelper.h" #include "unity-shared/BGHash.h" +#include "unity-shared/EMConverter.h" #include "unity-shared/Introspectable.h" #include "unity-shared/OverlayRenderer.h" #include "unity-shared/SearchBar.h" @@ -62,7 +63,7 @@ public: DashView(Scopes::Ptr const& scopes, ApplicationStarter::Ptr const& application_starter); ~DashView(); - void AboutToShow(); + void AboutToShow(int monitor); void AboutToHide(); void Relayout(); void DisableBlur(); @@ -129,6 +130,8 @@ private: nux::Geometry GetRenderAbsoluteGeometry() const; + void UpdateDashViewSize(); + void OnDPIChanged(); nux::Area* KeyNavIteration(nux::KeyNavDirection direction); @@ -192,6 +195,9 @@ private: nux::ObjectPtr<OverlayWindowButtons> overlay_window_buttons_; + EMConverter::Ptr cv_; + int monitor_; + friend class TestDashView; }; diff --git a/dash/FilterBar.cpp b/dash/FilterBar.cpp index 165523c3f..82bb4d51b 100644 --- a/dash/FilterBar.cpp +++ b/dash/FilterBar.cpp @@ -33,12 +33,19 @@ namespace unity { namespace dash { + +namespace +{ + double const DEFAULT_SCALE = 1.0; +} + DECLARE_LOGGER(logger, "unity.dash.filterbar"); NUX_IMPLEMENT_OBJECT_TYPE(FilterBar); FilterBar::FilterBar(NUX_FILE_LINE_DECL) : View(NUX_FILE_LINE_PARAM) + , scale_(DEFAULT_SCALE) { Init(); } @@ -57,6 +64,18 @@ void FilterBar::Init() SetLayout(layout); } +void FilterBar::UpdateScale(double scale) +{ + if (scale_ != scale) + { + scale_ = scale; + for (auto& filters : filter_map_) + { + filters.second->UpdateScale(scale_); + } + } +} + void FilterBar::SetFilters(Filters::Ptr const& filters) { filters_ = filters; @@ -71,6 +90,7 @@ void FilterBar::AddFilter(Filter::Ptr const& filter) } FilterExpanderLabel* filter_view = factory_.WidgetForFilter(filter); + filter_view->UpdateScale(scale_); AddChild(filter_view); filter_map_[filter] = filter_view; GetLayout()->AddView(filter_view, 0, nux::MINOR_POSITION_START, nux::MINOR_SIZE_FULL); diff --git a/dash/FilterBar.h b/dash/FilterBar.h index e437c43bb..9508d6871 100644 --- a/dash/FilterBar.h +++ b/dash/FilterBar.h @@ -46,6 +46,8 @@ public: void SetFilters(Filters::Ptr const& filters); + void UpdateScale(double scale); + void AddFilter(Filter::Ptr const& filter); void RemoveFilter(Filter::Ptr const& filter); void ClearFilters(); @@ -65,6 +67,8 @@ private: FilterFactory factory_; Filters::Ptr filters_; std::map<Filter::Ptr, FilterExpanderLabel*> filter_map_; + + double scale_; }; } // namespace dash diff --git a/dash/FilterExpanderLabel.cpp b/dash/FilterExpanderLabel.cpp index 2e337e466..a46600ad9 100644 --- a/dash/FilterExpanderLabel.cpp +++ b/dash/FilterExpanderLabel.cpp @@ -22,6 +22,7 @@ #include "unity-shared/DashStyle.h" #include "unity-shared/GraphicsUtils.h" +#include "unity-shared/RawPixel.h" #include "FilterExpanderLabel.h" namespace @@ -76,6 +77,11 @@ namespace unity namespace dash { +namespace +{ + double const DEFAULT_SCALE = 1.0; +} + NUX_IMPLEMENT_OBJECT_TYPE(FilterExpanderLabel); FilterExpanderLabel::FilterExpanderLabel(std::string const& label, NUX_FILE_LINE_DECL) @@ -89,6 +95,7 @@ FilterExpanderLabel::FilterExpanderLabel(std::string const& label, NUX_FILE_LINE , cairo_label_(nullptr) , raw_label_(label) , label_("label") + , scale_(DEFAULT_SCALE) { expanded.changed.connect(sigc::mem_fun(this, &FilterExpanderLabel::DoExpandChange)); BuildLayout(); @@ -101,13 +108,22 @@ void FilterExpanderLabel::SetLabel(std::string const& label) cairo_label_->SetText(label.c_str()); } +void FilterExpanderLabel::UpdateScale(double scale) +{ + if (scale_ != scale) + { + scale_ = scale; + cairo_label_->SetScale(scale); + } +} + void FilterExpanderLabel::SetRightHandView(nux::View* view) { dash::Style& style = dash::Style::Instance(); if (right_hand_contents_) { top_bar_layout_->RemoveChildObject(right_hand_contents_); - right_hand_contents_ = nullptr; + right_hand_contents_ = nullptr; } if (view) { diff --git a/dash/FilterExpanderLabel.h b/dash/FilterExpanderLabel.h index 1b15a92aa..62c0d43a0 100644 --- a/dash/FilterExpanderLabel.h +++ b/dash/FilterExpanderLabel.h @@ -59,6 +59,8 @@ public: void SetLabel(std::string const& label); void SetContents(nux::Layout* layout); + void UpdateScale(double scale); + virtual void SetFilter(Filter::Ptr const& filter) = 0; virtual std::string GetFilterType() = 0; @@ -97,6 +99,8 @@ private: nux::ObjectPtr<nux::Layout> contents_; std::unique_ptr<nux::AbstractPaintLayer> focus_layer_; + + double scale_; }; } // namespace dash diff --git a/dash/PlacesGroup.cpp b/dash/PlacesGroup.cpp index 3e11183fc..414b07e0d 100755 --- a/dash/PlacesGroup.cpp +++ b/dash/PlacesGroup.cpp @@ -33,6 +33,7 @@ #include "unity-shared/UBusWrapper.h" #include "unity-shared/UBusMessages.h" #include "unity-shared/GraphicsUtils.h" +#include "unity-shared/RawPixel.h" #include "ResultView.h" #include "ResultViewGrid.h" @@ -54,12 +55,16 @@ const nux::Color kExpandDefaultTextColor(1.0f, 1.0f, 1.0f, 0.5f); const float kExpandDefaultIconOpacity = 0.5f; // Category highlight -const int kHighlightHeight = 24; -const int kHighlightRightPadding = 10 - 3; // -3 because the scrollbar is not a real overlay scrollbar! -const int kHighlightLeftPadding = 10; +const RawPixel kHighlightRightPadding = 7_em; // FIXME 10 - 3 because the scrollbar is not a real overlay scrollbar! +const RawPixel kHighlightHeight = 24_em; +const RawPixel kHighlightLeftPadding = 10_em; +const RawPixel SPACE_BETWEEN_CHILDREN = 10_em; +const RawPixel TEXT_INTERNAL_MARGIN = 15_em; +const RawPixel EXPAND_INTERNAL_MARGIN = 8_em; +const double DEFAULT_SCALE = 1.0; // Font -const char* const NAME_LABEL_FONT = "Ubuntu 13"; // 17px = 13 +const char* const NAME_LABEL_FONT = "Ubuntu 13"; // 17px = 13 const char* const EXPANDER_LABEL_FONT = "Ubuntu 10"; // 13px = 10 } @@ -121,7 +126,8 @@ PlacesGroup::PlacesGroup(dash::StyleInterface& style) _n_visible_items_in_unexpand_mode(0), _n_total_items(0), _coverflow_enabled(false), - disabled_header_count_(false) + _disabled_header_count(false), + _scale(DEFAULT_SCALE) { SetAcceptKeyNavFocusOnMouseDown(false); SetAcceptKeyNavFocusOnMouseEnter(false); @@ -145,23 +151,22 @@ PlacesGroup::PlacesGroup(dash::StyleInterface& style) _group_layout = new nux::VLayout("", NUX_TRACKER_LOCATION); - int top_space = style.GetPlacesGroupTopSpace(); - _group_layout->AddLayout(new nux::SpaceLayout(top_space, top_space, top_space, top_space), 0); + // Spacelayout size is updated in UpdatePlacesGroupSize + _space_layout = new nux::SpaceLayout(0, 0, 0, 0); + _group_layout->AddLayout(_space_layout, 0); _header_view = new HeaderView(NUX_TRACKER_LOCATION); _group_layout->AddView(_header_view, 0, nux::MINOR_POSITION_START, nux::MINOR_SIZE_FULL); _header_layout = new nux::HLayout(NUX_TRACKER_LOCATION); _header_layout->SetLeftAndRightPadding(_style.GetCategoryHeaderLeftPadding(), 0); - _header_layout->SetSpaceBetweenChildren(10); _header_view->SetLayout(_header_layout); - _icon = new IconTexture("", _style.GetCategoryIconSize()); - _icon->SetMinMaxSize(_style.GetCategoryIconSize(), _style.GetCategoryIconSize()); + RawPixel const icon_size = _style.GetCategoryIconSize(); + _icon = new IconTexture("", icon_size.CP(_scale)); _header_layout->AddView(_icon, 0, nux::MINOR_POSITION_CENTER, nux::MINOR_SIZE_FIX); _text_layout = new nux::HLayout(NUX_TRACKER_LOCATION); - _text_layout->SetHorizontalInternalMargin(15); _header_layout->AddLayout(_text_layout, 0, nux::MINOR_POSITION_CENTER, nux::MINOR_SIZE_MATCHCONTENT); _name = new StaticCairoText("", NUX_TRACKER_LOCATION); @@ -171,7 +176,6 @@ PlacesGroup::PlacesGroup(dash::StyleInterface& style) _text_layout->AddView(_name, 0, nux::MINOR_POSITION_CENTER, nux::MINOR_SIZE_MATCHCONTENT); _expand_layout = new nux::HLayout(NUX_TRACKER_LOCATION); - _expand_layout->SetHorizontalInternalMargin(8); _text_layout->AddLayout(_expand_layout, 0, nux::MINOR_POSITION_END, nux::MINOR_SIZE_MATCHCONTENT); _expand_label_layout = new nux::HLayout(NUX_TRACKER_LOCATION); @@ -211,6 +215,53 @@ PlacesGroup::PlacesGroup(dash::StyleInterface& style) else nux::GetWindowCompositor().SetKeyFocusArea(GetHeaderFocusableView(), direction); }); + + UpdatePlacesGroupSize(); +} + +void +PlacesGroup::UpdatePlacesGroupSize() +{ + RawPixel const icon_size = _style.GetCategoryIconSize(); + RawPixel const group_top = _style.GetPlacesGroupTopSpace(); + + int top_space = group_top.CP(_scale); + _space_layout->SetMinimumSize(top_space, top_space); + _space_layout->SetMaximumSize(top_space, top_space); + + _header_layout->SetSpaceBetweenChildren(SPACE_BETWEEN_CHILDREN.CP(_scale)); + + _icon->SetMinMaxSize(icon_size.CP(_scale), icon_size.CP(_scale)); + + _text_layout->SetHorizontalInternalMargin(TEXT_INTERNAL_MARGIN.CP(_scale)); + _expand_layout->SetHorizontalInternalMargin(EXPAND_INTERNAL_MARGIN.CP(_scale)); +} + +void +PlacesGroup::UpdateScale(double scale) +{ + if (_scale != scale) + { + RawPixel const icon_size = _style.GetCategoryIconSize(); + + _scale = scale; + _name->SetScale(_scale); + _expand_label->SetScale(_scale); + + _icon->SetSize(icon_size.CP(_scale)); + _icon->ReLoadIcon(); + + // FIXME _expand_icon, needs some work here. Not as easy as _icon + + if (_child_view) + { + _child_view->UpdateScale(scale); + } + + ComputeContentSize(); + UpdatePlacesGroupSize(); + UpdateResultViewPadding(); + } } void @@ -232,6 +283,8 @@ PlacesGroup::OnLabelFocusChanged(nux::Area* label, bool has_focus, nux::KeyNavDi } void + +// FIXME _expand_icon, needs some work here. Not as easy as _icon PlacesGroup::SetName(std::string const& name) { if (_cached_name != name) @@ -243,7 +296,7 @@ PlacesGroup::SetName(std::string const& name) void PlacesGroup::SetHeaderCountVisible(bool disable) { - disabled_header_count_ = !disable; + _disabled_header_count = !disable; Relayout(); } @@ -266,6 +319,19 @@ PlacesGroup::SetIcon(std::string const& path_to_emblem) } void +PlacesGroup::UpdateResultViewPadding() +{ + if (_child_layout) + { + RawPixel const result_top_padding = _style.GetPlacesGroupResultTopPadding(); + RawPixel const result_left_padding = _style.GetPlacesGroupResultLeftPadding(); + + _child_layout->SetTopAndBottomPadding(result_top_padding.CP(_scale), 0); + _child_layout->SetLeftAndRightPadding(result_left_padding.CP(_scale), 0); + } +} + +void PlacesGroup::SetChildView(dash::ResultView* view) { if (_child_view) @@ -279,12 +345,12 @@ PlacesGroup::SetChildView(dash::ResultView* view) AddChild(view); _child_view = view; + _child_view->UpdateScale(_scale); _child_layout = new nux::VLayout(); _child_layout->AddView(_child_view, 0); - _child_layout->SetTopAndBottomPadding(_style.GetPlacesGroupResultTopPadding(),0); - _child_layout->SetLeftAndRightPadding(_style.GetPlacesGroupResultLeftPadding(), 0); + UpdateResultViewPadding(); _group_layout->AddLayout(_child_layout, 1); view->results_per_row.changed.connect([this] (int results_per_row) @@ -311,7 +377,7 @@ void PlacesGroup::SetChildLayout(nux::Layout* layout) void PlacesGroup::RefreshLabel() { - if (disabled_header_count_) + if (_disabled_header_count) { _expand_icon->SetVisible(false); _expand_label->SetVisible(false); @@ -401,7 +467,10 @@ long PlacesGroup::ComputeContentSize() // only the width matters if (_cached_geometry.GetWidth() != geo.GetWidth()) { - _focus_layer.reset(_style.FocusOverlay(geo.width - kHighlightLeftPadding - kHighlightRightPadding, kHighlightHeight)); + _focus_layer.reset(_style.FocusOverlay(geo.width - + kHighlightLeftPadding.CP(_scale) - + kHighlightRightPadding.CP(_scale), + kHighlightHeight.CP(_scale))); _cached_geometry = geo; } return ret; @@ -419,8 +488,11 @@ void PlacesGroup::Draw(nux::GraphicsEngine& graphics_engine, if (ShouldBeHighlighted() && _focus_layer) { nux::Geometry geo(_header_layout->GetGeometry()); - geo.width = base.width - kHighlightRightPadding - kHighlightLeftPadding; - geo.x += kHighlightLeftPadding; + geo.width = base.width - + kHighlightRightPadding.CP(_scale) - + kHighlightLeftPadding.CP(_scale); + + geo.x += kHighlightLeftPadding.CP(_scale); _focus_layer->SetGeometry(geo); _focus_layer->Renderlayer(graphics_engine); diff --git a/dash/PlacesGroup.h b/dash/PlacesGroup.h index 28cb1f432..536be4fc1 100644 --- a/dash/PlacesGroup.h +++ b/dash/PlacesGroup.h @@ -69,7 +69,6 @@ public: void SetChildView(dash::ResultView* view); dash::ResultView* GetChildView(); - void SetChildLayout(nux::Layout* layout); void Relayout(); @@ -95,6 +94,8 @@ public: glib::Variant GetCurrentFocus() const; void SetCurrentFocus(glib::Variant const& variant); + void UpdateScale(double scale); + protected: long ComputeContentSize(); @@ -123,6 +124,9 @@ private: bool OnIdleRelayout(); void RefreshLabel(); + void UpdatePlacesGroupSize(); + void UpdateResultViewPadding(); + private: std::string _category_id; dash::StyleInterface& _style; @@ -134,13 +138,14 @@ private: nux::HLayout* _expand_label_layout; nux::HLayout* _expand_layout; nux::VLayout* _child_layout; + nux::SpaceLayout* _space_layout; dash::ResultView* _child_view; std::unique_ptr<nux::AbstractPaintLayer> _focus_layer; - IconTexture* _icon; + IconTexture* _icon; StaticCairoText* _name; StaticCairoText* _expand_label; - IconTexture* _expand_icon; + IconTexture* _expand_icon; nux::BaseTexture* _background; nux::BaseTexture* _background_nofilters; @@ -156,11 +161,13 @@ private: bool _coverflow_enabled; - bool disabled_header_count_; + bool _disabled_header_count; glib::Source::UniquePtr _relayout_idle; UBusManager _ubus; + double _scale; + friend class TestScopeView; }; diff --git a/dash/ResultRenderer.cpp b/dash/ResultRenderer.cpp index 7b92ff45c..ed8d567e1 100644 --- a/dash/ResultRenderer.cpp +++ b/dash/ResultRenderer.cpp @@ -108,6 +108,8 @@ GdkPixbuf* _icon_hint_get_drag_pixbuf(std::string icon_hint, int size) return pbuf; } +double const DEFAULT_SCALE = 1.0; + } NUX_IMPLEMENT_OBJECT_TYPE(ResultRenderer); @@ -116,6 +118,7 @@ ResultRenderer::ResultRenderer(NUX_FILE_LINE_DECL) : InitiallyUnownedObject(NUX_FILE_LINE_PARAM) , width(50) , height(50) + , scale_(DEFAULT_SCALE) {} void ResultRenderer::Render(nux::GraphicsEngine& GfxContext, @@ -144,6 +147,11 @@ nux::NBitmapData* ResultRenderer::GetDndImage(Result const& row) const return graphics.GetBitmap(); } +void ResultRenderer::UpdateScale(double scale) +{ + scale_ = scale; +} + } } diff --git a/dash/ResultRenderer.h b/dash/ResultRenderer.h index 63a36bcd0..b53ad5398 100644 --- a/dash/ResultRenderer.h +++ b/dash/ResultRenderer.h @@ -65,13 +65,20 @@ public: // unload any previous grabbed images virtual void Unload(Result const& row); + virtual void ReloadResult(Result const& row) {} + // get a image to drag virtual nux::NBitmapData* GetDndImage(Result const& row) const; + virtual void UpdateScale(double scale); + nux::Property<int> width; nux::Property<int> height; sigc::signal<void> NeedsRedraw; + +protected: + double scale_; }; } diff --git a/dash/ResultRendererHorizontalTile.cpp b/dash/ResultRendererHorizontalTile.cpp index 26b13ac9b..12068f929 100644 --- a/dash/ResultRendererHorizontalTile.cpp +++ b/dash/ResultRendererHorizontalTile.cpp @@ -29,6 +29,7 @@ #include "unity-shared/CairoTexture.h" #include "unity-shared/TextureCache.h" +#include "unity-shared/RawPixel.h" #include <NuxGraphics/GdkGraphics.h> @@ -36,14 +37,14 @@ namespace unity { namespace { -const int CARD_VIEW_PADDING = 4; // pixels -const int CARD_VIEW_ICON_SIZE = 64; // pixels -const int CARD_VIEW_ICON_TEXT_GAP = 10; // pixels -const int CARD_VIEW_WIDTH = 277; // pixels -const int CARD_VIEW_HEIGHT = 74; // pixels -const int CARD_VIEW_HIGHLIGHT_CORNER_RADIUS = 2; // pixels -const int CARD_VIEW_ICON_OUTLINE_WIDTH = 1; // pixels -const int CARD_VIEW_TEXT_LINE_SPACING = 0; // points +RawPixel const CARD_VIEW_PADDING = 4_em; +RawPixel const CARD_VIEW_ICON_SIZE = 64_em; +RawPixel const CARD_VIEW_ICON_TEXT_GAP = 10_em; +RawPixel const CARD_VIEW_WIDTH = 277_em; +RawPixel const CARD_VIEW_HEIGHT = 74_em; +RawPixel const CARD_VIEW_HIGHLIGHT_CORNER_RADIUS = 2_em; +RawPixel const CARD_VIEW_ICON_OUTLINE_WIDTH = 1_em; +RawPixel const CARD_VIEW_TEXT_LINE_SPACING = 0_em; void RenderTexture(nux::GraphicsEngine& GfxContext, int x, @@ -88,19 +89,31 @@ NUX_IMPLEMENT_OBJECT_TYPE(ResultRendererHorizontalTile); ResultRendererHorizontalTile::ResultRendererHorizontalTile(NUX_FILE_LINE_DECL) : ResultRendererTile(NUX_FILE_LINE_PARAM) { - width = CARD_VIEW_WIDTH; - height = CARD_VIEW_HEIGHT; + ReloadTextures(); +} + +void ResultRendererHorizontalTile::UpdateScale(double scale) +{ + ResultRenderer::UpdateScale(scale); + ReloadTextures(); +} + +void ResultRendererHorizontalTile::ReloadTextures() +{ + width = CARD_VIEW_WIDTH.CP(scale_); + height = CARD_VIEW_HEIGHT.CP(scale_); // pre-load the highlight texture // try and get a texture from the texture cache TextureCache& cache = TextureCache::GetDefault(); prelight_cache_ = cache.FindTexture("ResultRendererHorizontalTile.PreLightTexture", - CARD_VIEW_WIDTH, - CARD_VIEW_HEIGHT, + width, + height, sigc::mem_fun(this, &ResultRendererHorizontalTile::DrawHighlight)); + normal_cache_ = cache.FindTexture("ResultRendererHorizontalTile.NormalTexture", - CARD_VIEW_WIDTH, - CARD_VIEW_HEIGHT, + width, + height, sigc::mem_fun(this, &ResultRendererHorizontalTile::DrawNormal)); } @@ -120,16 +133,16 @@ void ResultRendererHorizontalTile::Render(nux::GraphicsEngine& GfxContext, // set up our texture mode nux::TexCoordXForm texxform; - int icon_left_hand_side = geometry.x + padding; - int icon_top_side = geometry.y + ((geometry.height - CARD_VIEW_ICON_SIZE) / 2); + int icon_left_hand_side = geometry.x + Padding(); + int icon_top_side = geometry.y + ((geometry.height - CARD_VIEW_ICON_SIZE.CP(scale_)) / 2); // render overall tile background "rectangle" if (state == ResultRendererState::RESULT_RENDERER_NORMAL) { int x = icon_left_hand_side; int y = icon_top_side; - int w = CARD_VIEW_WIDTH; - int h = CARD_VIEW_HEIGHT; + int w = CARD_VIEW_WIDTH.CP(scale_); + int h = CARD_VIEW_HEIGHT.CP(scale_); unsigned int alpha = 0; unsigned int src = 0; @@ -155,8 +168,8 @@ void ResultRendererHorizontalTile::Render(nux::GraphicsEngine& GfxContext, { int x = icon_left_hand_side; int y = icon_top_side; - int w = CARD_VIEW_WIDTH; - int h = CARD_VIEW_HEIGHT; + int w = CARD_VIEW_WIDTH.CP(scale_); + int h = CARD_VIEW_HEIGHT.CP(scale_); RenderTexture(GfxContext, x, @@ -172,15 +185,15 @@ void ResultRendererHorizontalTile::Render(nux::GraphicsEngine& GfxContext, // draw the icon if (container->icon) { - int x = icon_left_hand_side + CARD_VIEW_PADDING + CARD_VIEW_ICON_OUTLINE_WIDTH; - int y = icon_top_side + CARD_VIEW_PADDING + CARD_VIEW_ICON_OUTLINE_WIDTH; - int w = CARD_VIEW_ICON_SIZE; - int h = CARD_VIEW_ICON_SIZE; + int x = icon_left_hand_side + CARD_VIEW_PADDING.CP(scale_) + CARD_VIEW_ICON_OUTLINE_WIDTH.CP(scale_); + int y = icon_top_side + CARD_VIEW_PADDING.CP(scale_) + CARD_VIEW_ICON_OUTLINE_WIDTH.CP(scale_); + int w = CARD_VIEW_ICON_SIZE.CP(scale_); + int h = CARD_VIEW_ICON_SIZE.CP(scale_); gPainter.Paint2DQuadColor(GfxContext, - x - CARD_VIEW_ICON_OUTLINE_WIDTH, - y - CARD_VIEW_ICON_OUTLINE_WIDTH, - w + 2 * CARD_VIEW_ICON_OUTLINE_WIDTH, - h + 2 * CARD_VIEW_ICON_OUTLINE_WIDTH, + x - CARD_VIEW_ICON_OUTLINE_WIDTH.CP(scale_), + y - CARD_VIEW_ICON_OUTLINE_WIDTH.CP(scale_), + w + 2 * CARD_VIEW_ICON_OUTLINE_WIDTH.CP(scale_), + h + 2 * CARD_VIEW_ICON_OUTLINE_WIDTH.CP(scale_), nux::color::Black); RenderTexture(GfxContext, x, @@ -195,8 +208,13 @@ void ResultRendererHorizontalTile::Render(nux::GraphicsEngine& GfxContext, if (container->text) { - int x = icon_left_hand_side + CARD_VIEW_PADDING + 2 * CARD_VIEW_ICON_OUTLINE_WIDTH + CARD_VIEW_ICON_SIZE + CARD_VIEW_ICON_TEXT_GAP; - int y = icon_top_side + CARD_VIEW_PADDING; + int x = icon_left_hand_side + + CARD_VIEW_PADDING.CP(scale_) + + 2 * CARD_VIEW_ICON_OUTLINE_WIDTH.CP(scale_) + + CARD_VIEW_ICON_SIZE.CP(scale_) + + CARD_VIEW_ICON_TEXT_GAP.CP(scale_); + + int y = icon_top_side + CARD_VIEW_PADDING.CP(scale_); int w = container->text->GetWidth(); int h = container->text->GetHeight(); @@ -231,7 +249,7 @@ nux::BaseTexture* ResultRendererHorizontalTile::DrawHighlight(std::string const& 1.0f, 0.0f, 0.0f, - CARD_VIEW_HIGHLIGHT_CORNER_RADIUS, + CARD_VIEW_HIGHLIGHT_CORNER_RADIUS.CP(scale_), width, height, false); @@ -259,7 +277,7 @@ nux::BaseTexture* ResultRendererHorizontalTile::DrawNormal(std::string const& te 1.0f, 0.0f, 0.0f, - CARD_VIEW_HIGHLIGHT_CORNER_RADIUS, + CARD_VIEW_HIGHLIGHT_CORNER_RADIUS.CP(scale_), width, height, false); @@ -283,8 +301,13 @@ void ResultRendererHorizontalTile::LoadText(Result const& row) g_free(comment); nux::CairoGraphics _cairoGraphics(CAIRO_FORMAT_ARGB32, - CARD_VIEW_WIDTH - CARD_VIEW_ICON_SIZE - 2 * CARD_VIEW_ICON_OUTLINE_WIDTH - 2 * CARD_VIEW_PADDING - CARD_VIEW_ICON_TEXT_GAP, - CARD_VIEW_HEIGHT - 2 * CARD_VIEW_PADDING); + CARD_VIEW_WIDTH.CP(scale_) - + CARD_VIEW_ICON_SIZE.CP(scale_) - + 2 * CARD_VIEW_ICON_OUTLINE_WIDTH.CP(scale_) - + 2 * CARD_VIEW_PADDING.CP(scale_) - + CARD_VIEW_ICON_TEXT_GAP.CP(scale_), + CARD_VIEW_HEIGHT.CP(scale_) - + 2 * CARD_VIEW_PADDING.CP(scale_)); cairo_t* cr = _cairoGraphics.GetContext(); @@ -305,8 +328,13 @@ void ResultRendererHorizontalTile::LoadText(Result const& row) pango_layout_set_wrap(layout, PANGO_WRAP_WORD_CHAR); pango_layout_set_ellipsize(layout, PANGO_ELLIPSIZE_END); - pango_layout_set_spacing(layout, CARD_VIEW_TEXT_LINE_SPACING * PANGO_SCALE); - pango_layout_set_width(layout, (CARD_VIEW_WIDTH - CARD_VIEW_ICON_SIZE - 2 * CARD_VIEW_ICON_OUTLINE_WIDTH - 2 * CARD_VIEW_PADDING - CARD_VIEW_ICON_TEXT_GAP) * PANGO_SCALE); + pango_layout_set_spacing(layout, CARD_VIEW_TEXT_LINE_SPACING.CP(scale_) * PANGO_SCALE); + pango_layout_set_width(layout, (CARD_VIEW_WIDTH.CP(scale_) - + CARD_VIEW_ICON_SIZE.CP(scale_) - + 2 * CARD_VIEW_ICON_OUTLINE_WIDTH.CP(scale_) - + 2 * CARD_VIEW_PADDING.CP(scale_) - + CARD_VIEW_ICON_TEXT_GAP.CP(scale_)) * PANGO_SCALE); + pango_layout_set_height(layout, -4); pango_layout_set_markup(layout, final_text.str().c_str(), -1); @@ -328,7 +356,7 @@ void ResultRendererHorizontalTile::LoadText(Result const& row) PangoRectangle logRect = {0, 0, 0, 0}; pango_layout_get_extents(layout, NULL, &logRect); if (pango_layout_get_line_count(layout) < 4) - offset = ((CARD_VIEW_HEIGHT - 2 * CARD_VIEW_PADDING) - (logRect.height / PANGO_SCALE)) / 2.0; + offset = ((CARD_VIEW_HEIGHT.CP(scale_) - 2 * CARD_VIEW_PADDING.CP(scale_)) - (logRect.height / PANGO_SCALE)) / 2.0; cairo_move_to(cr, 0.0f, offset); pango_cairo_show_layout(cr, layout); @@ -353,9 +381,12 @@ nux::NBitmapData* ResultRendererHorizontalTile::GetDndImage(Result const& row) c int width = gdk_pixbuf_get_width(container->drag_icon); int height = gdk_pixbuf_get_height(container->drag_icon); - if (width != CARD_VIEW_ICON_SIZE || height != CARD_VIEW_ICON_SIZE) + if (width != CARD_VIEW_ICON_SIZE.CP(scale_) || height != CARD_VIEW_ICON_SIZE.CP(scale_)) { - nux::GdkGraphics graphics(gdk_pixbuf_scale_simple(container->drag_icon, CARD_VIEW_ICON_SIZE, CARD_VIEW_ICON_SIZE, GDK_INTERP_BILINEAR)); + nux::GdkGraphics graphics(gdk_pixbuf_scale_simple(container->drag_icon, + CARD_VIEW_ICON_SIZE.CP(scale_), + CARD_VIEW_ICON_SIZE.CP(scale_), + GDK_INTERP_BILINEAR)); bitmap = graphics.GetBitmap(); } } diff --git a/dash/ResultRendererHorizontalTile.h b/dash/ResultRendererHorizontalTile.h index 2b9544d0c..1fdf2e259 100644 --- a/dash/ResultRendererHorizontalTile.h +++ b/dash/ResultRendererHorizontalTile.h @@ -51,10 +51,14 @@ public: virtual nux::NBitmapData* GetDndImage(Result const& row) const; + void UpdateScale(double scale); + protected: virtual void LoadText(Result const& row); private: + void ReloadTextures(); + nux::BaseTexture* DrawHighlight(std::string const& texid, int width, int height); nux::BaseTexture* DrawNormal(std::string const& texid, diff --git a/dash/ResultRendererTile.cpp b/dash/ResultRendererTile.cpp index c85cf941f..5075565df 100644 --- a/dash/ResultRendererTile.cpp +++ b/dash/ResultRendererTile.cpp @@ -31,12 +31,7 @@ #include "unity-shared/CairoTexture.h" #include "unity-shared/DashStyle.h" #include "unity-shared/TextureCache.h" - -namespace -{ -bool neko; -#define DEFAULT_GICON ". GThemedIcon text-x-preview" -} +#include "unity-shared/RawPixel.h" namespace unity { @@ -44,10 +39,15 @@ DECLARE_LOGGER(logger, "unity.dash.results"); namespace { -const int FONT_SIZE = 10; -const char REPLACEMENT_CHAR = '?'; -const float CORNER_HIGHTLIGHT_RADIUS = 2.0f; +std::string const DEFAULT_GICON = ". GThemedIcon text-x-preview"; +RawPixel const PADDING = 6_em; +RawPixel const SPACING = 10_em; +RawPixel const FONT_SIZE = 10_em; +int const FONT_MULTIPLIER = 1024; + +char const REPLACEMENT_CHAR = '?'; +float const CORNER_HIGHTLIGHT_RADIUS = 2.0f; void RenderTexture(nux::GraphicsEngine& GfxContext, int x, @@ -92,17 +92,24 @@ NUX_IMPLEMENT_OBJECT_TYPE(ResultRendererTile); ResultRendererTile::ResultRendererTile(NUX_FILE_LINE_DECL) : ResultRenderer(NUX_FILE_LINE_PARAM) - , spacing(10) - , padding(6) { - dash::Style& style = dash::Style::Instance(); - width = style.GetTileWidth(); - height = style.GetTileHeight(); - - gsize tmp; - gchar* tmp1 = (gchar*)g_base64_decode("VU5JVFlfTkVLTw==", &tmp); - neko = (g_getenv(tmp1)); - g_free (tmp1); + UpdateWidthHeight(); +} + +void ResultRendererTile::UpdateWidthHeight() +{ + dash::Style const& style = dash::Style::Instance(); + RawPixel tile_width = style.GetTileWidth(); + RawPixel tile_height = style.GetTileHeight(); + + width = tile_width.CP(scale_); + height = tile_height.CP(scale_); +} + +void ResultRendererTile::UpdateScale(double scale) +{ + ResultRenderer::UpdateScale(scale); + UpdateWidthHeight(); } void ResultRendererTile::Render(nux::GraphicsEngine& GfxContext, @@ -117,8 +124,14 @@ void ResultRendererTile::Render(nux::GraphicsEngine& GfxContext, if (container == nullptr) return; - dash::Style& style = dash::Style::Instance(); - int tile_icon_size = style.GetTileImageSize(); + dash::Style const& style = dash::Style::Instance(); + RawPixel const tile_size = style.GetTileImageSize(); + RawPixel const tile_width = style.GetTileWidth(); + RawPixel const tile_height = style.GetTileHeight(); + RawPixel const tile_highlight_width = style.GetTileIconHightlightWidth(); + RawPixel const tile_highlight_height = style.GetTileIconHightlightHeight(); + + int tile_icon_size = tile_size.CP(scale_); // set up our texture mode nux::TexCoordXForm texxform; @@ -135,13 +148,13 @@ void ResultRendererTile::Render(nux::GraphicsEngine& GfxContext, } int icon_left_hand_side = geometry.x + (geometry.width - icon_width) / 2; - int icon_top_side = geometry.y + padding + (tile_icon_size - icon_height) / 2; + int icon_top_side = geometry.y + PADDING.CP(scale_) + (tile_icon_size - icon_height) / 2; // render highlight if its needed if (container->prelight && state != ResultRendererState::RESULT_RENDERER_NORMAL) { - int highlight_x = (geometry.x + geometry.width/2) - style.GetTileIconHightlightWidth()/2; - int highlight_y = (geometry.y + padding + tile_icon_size / 2) - style.GetTileIconHightlightHeight()/2; + int highlight_x = (geometry.x + geometry.width/2) - tile_highlight_width.CP(scale_)/2; + int highlight_y = (geometry.y + PADDING.CP(scale_) + tile_icon_size / 2) - tile_highlight_height.CP(scale_)/2; RenderTexture(GfxContext, highlight_x, @@ -171,10 +184,10 @@ void ResultRendererTile::Render(nux::GraphicsEngine& GfxContext, if (container->text) { RenderTexture(GfxContext, - geometry.x + padding, - geometry.y + tile_icon_size + spacing, - style.GetTileWidth() - (padding * 2), - style.GetTileHeight() - tile_icon_size - spacing, + geometry.x + PADDING.CP(scale_), + geometry.y + tile_icon_size + SPACING.CP(scale_), + tile_width.CP(scale_) - (PADDING.CP(scale_) * 2), + tile_height.CP(scale_) - tile_icon_size - SPACING.CP(scale_), container->text->GetDeviceTexture(), texxform, color, @@ -209,6 +222,11 @@ nux::BaseTexture* ResultRendererTile::DrawHighlight(std::string const& texid, in return texture_from_cairo_graphics(cairo_graphics); } +int ResultRendererTile::Padding() const +{ + return PADDING.CP(scale_); +} + void ResultRendererTile::Preload(Result const& row) { if (row.renderer<TextureContainer*>() == nullptr) @@ -220,6 +238,17 @@ void ResultRendererTile::Preload(Result const& row) } } +void ResultRendererTile::ReloadResult(Result const& row) +{ + Unload(row); + + if (row.renderer<TextureContainer*>() == nullptr) + const_cast<Result&>(row).set_renderer(new TextureContainer()); + + LoadIcon(row); + LoadText(row); +} + void ResultRendererTile::Unload(Result const& row) { TextureContainer *container = row.renderer<TextureContainer*>(); @@ -247,23 +276,15 @@ nux::NBitmapData* ResultRendererTile::GetDndImage(Result const& row) const void ResultRendererTile::LoadIcon(Result const& row) { - Style& style = Style::Instance(); + Style const& style = Style::Instance(); + RawPixel const tile_size = style.GetTileImageSize(); + RawPixel const tile_gsize = style.GetTileGIconSize(); + RawPixel const tile_highlight_width = style.GetTileIconHightlightWidth(); + RawPixel const tile_highlight_height = style.GetTileIconHightlightHeight(); + std::string icon_hint(row.icon_hint); std::string icon_name; - if (G_UNLIKELY(neko)) - { - int tmp1 = style.GetTileGIconSize() + (rand() % 16) - 8; - gsize tmp3; - gchar* tmp2 = (gchar*)g_base64_decode("aHR0cDovL3BsYWNla2l0dGVuLmNvbS8laS8laS8=", &tmp3); - gchar* tmp4 = g_strdup_printf(tmp2, tmp1, tmp1); - icon_name = tmp4; - g_free(tmp4); - g_free(tmp2); - } - else - { - icon_name = !icon_hint.empty() ? icon_hint : DEFAULT_GICON; - } + icon_name = !icon_hint.empty() ? icon_hint : DEFAULT_GICON; glib::Object<GIcon> icon(g_icon_new_for_string(icon_name.c_str(), NULL)); TextureContainer* container = row.renderer<TextureContainer*>(); @@ -272,7 +293,10 @@ void ResultRendererTile::LoadIcon(Result const& row) { TextureCache& cache = TextureCache::GetDefault(); - BaseTexturePtr texture_prelight(cache.FindTexture("resultview_prelight", style.GetTileIconHightlightWidth(), style.GetTileIconHightlightHeight(), sigc::mem_fun(this, &ResultRendererTile::DrawHighlight))); + BaseTexturePtr texture_prelight(cache.FindTexture("resultview_prelight", + tile_highlight_width.CP(scale_), + tile_highlight_height.CP(scale_), + sigc::mem_fun(this, &ResultRendererTile::DrawHighlight))); container->prelight = texture_prelight; } @@ -281,11 +305,14 @@ void ResultRendererTile::LoadIcon(Result const& row) if (icon.IsType(G_TYPE_ICON)) { bool use_large_icon = icon.IsType(G_TYPE_FILE_ICON) || !icon.IsType(G_TYPE_THEMED_ICON); - container->slot_handle = IconLoader::GetDefault().LoadFromGIconString(icon_name, style.GetTileImageSize(), use_large_icon ? style.GetTileImageSize() : style.GetTileGIconSize(), slot); + container->slot_handle = IconLoader::GetDefault().LoadFromGIconString(icon_name, + tile_size.CP(scale_), + use_large_icon ? + tile_size.CP(scale_) : tile_gsize.CP(scale_), slot); } else { - container->slot_handle = IconLoader::GetDefault().LoadFromIconName(icon_name, -1, style.GetTileGIconSize(), slot); + container->slot_handle = IconLoader::GetDefault().LoadFromIconName(icon_name, -1, tile_gsize.CP(scale_), slot); } } @@ -312,14 +339,15 @@ nux::BaseTexture* ResultRendererTile::CreateTextureCallback(std::string const& t } else { + Style const& style = Style::Instance(); + RawPixel const tile_size = style.GetTileImageSize(); + // slow path for non square icons that must be resized to fit in the square // texture - - Style& style = Style::Instance(); float aspect = static_cast<float>(pixbuf_height) / pixbuf_width; // already sanitized width/height so can not be 0.0 if (aspect < 1.0f) { - pixbuf_width = style.GetTileImageSize(); + pixbuf_width = tile_size.CP(scale_); pixbuf_height = pixbuf_width * aspect; if (pixbuf_height > height) @@ -446,10 +474,14 @@ std::string ReplaceBlacklistedChars(std::string const& str) void ResultRendererTile::LoadText(Result const& row) { - Style& style = Style::Instance(); + Style const& style = Style::Instance(); + RawPixel const tile_size = style.GetTileImageSize(); + RawPixel const tile_width = style.GetTileWidth(); + RawPixel const tile_height = style.GetTileHeight(); + nux::CairoGraphics _cairoGraphics(CAIRO_FORMAT_ARGB32, - style.GetTileWidth() - (padding * 2), - style.GetTileHeight() - style.GetTileImageSize() - spacing); + tile_width.CP(scale_) - (PADDING.CP(scale_) * 2), + tile_height.CP(scale_) - tile_size.CP(scale_) - SPACING.CP(scale_)); cairo_t* cr = _cairoGraphics.GetContext(); @@ -466,14 +498,14 @@ void ResultRendererTile::LoadText(Result const& row) cairo_set_font_options(cr, gdk_screen_get_font_options(screen)); layout = pango_cairo_create_layout(cr); desc = pango_font_description_from_string(font.Value()); - pango_font_description_set_size (desc, FONT_SIZE * PANGO_SCALE); + pango_font_description_set_size (desc, FONT_SIZE.CP(scale_) * FONT_MULTIPLIER); pango_layout_set_font_description(layout, desc); pango_layout_set_alignment(layout, PANGO_ALIGN_CENTER); pango_layout_set_wrap(layout, PANGO_WRAP_WORD_CHAR); pango_layout_set_ellipsize(layout, PANGO_ELLIPSIZE_START); - pango_layout_set_width(layout, (style.GetTileWidth() - (padding * 2))* PANGO_SCALE); + pango_layout_set_width(layout, (tile_width.CP(scale_) - (PADDING.CP(scale_) * 2))* PANGO_SCALE); pango_layout_set_height(layout, -2); // FIXME bug #1239381 diff --git a/dash/ResultRendererTile.h b/dash/ResultRendererTile.h index e556dd0e0..5c41c1419 100644 --- a/dash/ResultRendererTile.h +++ b/dash/ResultRendererTile.h @@ -75,8 +75,10 @@ public: virtual nux::NBitmapData* GetDndImage(Result const& row) const; - int spacing; - int padding; + void ReloadResult(Result const& row); + void UpdateScale(double scale) override; + + int Padding() const; protected: virtual void LoadText(Result const& row); @@ -93,6 +95,8 @@ private: glib::Object<GdkPixbuf> const& pixbuf); nux::BaseTexture* DrawHighlight(std::string const& texid, int width, int height); + + void UpdateWidthHeight(); }; } diff --git a/dash/ResultView.cpp b/dash/ResultView.cpp index 556f19ab9..d0b9cd193 100644 --- a/dash/ResultView.cpp +++ b/dash/ResultView.cpp @@ -33,6 +33,11 @@ namespace unity namespace dash { +namespace +{ + double const DEFAULT_SCALE = 1.0; +} + NUX_IMPLEMENT_OBJECT_TYPE(ResultView); ResultView::ResultView(NUX_FILE_LINE_DECL) @@ -41,6 +46,7 @@ ResultView::ResultView(NUX_FILE_LINE_DECL) , desaturation_progress(0.0) , enable_texture_render(false) , renderer_(NULL) + , scale_(DEFAULT_SCALE) , cached_result_(nullptr, nullptr, nullptr) { expanded.changed.connect([this](bool value) @@ -73,6 +79,26 @@ ResultView::~ResultView() renderer_->UnReference(); } +void ResultView::UpdateScale(double scale) +{ + if (scale_ != scale) + { + scale_ = scale; + + if (renderer_) + { + renderer_->UpdateScale(scale_); + + for (auto it = result_model_->begin(); it != result_model_->end(); ++it) + { + renderer_->ReloadResult(*it); + } + + NeedRedraw(); + } + } +} + void ResultView::SetModelRenderer(ResultRenderer* renderer) { if (renderer_ != NULL) diff --git a/dash/ResultView.h b/dash/ResultView.h index a3a9d1954..0abbb5f91 100644 --- a/dash/ResultView.h +++ b/dash/ResultView.h @@ -88,6 +88,8 @@ public: void AddProperties(debug::IntrospectionData&); IntrospectableList GetIntrospectableChildren(); + virtual void UpdateScale(double scale); + virtual int GetSelectedIndex() const; virtual void SetSelectedIndex(int index); @@ -121,6 +123,8 @@ protected: std::vector<ResultViewTexture::Ptr> result_textures_; + double scale_; + private: void OnRowAdded(DeeModel* model, DeeModelIter* iter); void OnRowRemoved(DeeModel* model, DeeModelIter* iter); diff --git a/dash/ResultViewGrid.cpp b/dash/ResultViewGrid.cpp index 757facca6..ffe47d12f 100644 --- a/dash/ResultViewGrid.cpp +++ b/dash/ResultViewGrid.cpp @@ -33,6 +33,7 @@ #include "unity-shared/UBusWrapper.h" #include "unity-shared/UBusMessages.h" #include "unity-shared/GraphicsUtils.h" +#include "unity-shared/RawPixel.h" #include "unity-shared/UnitySettings.h" #include "unity-shared/WindowManager.h" #include "ResultViewGrid.h" @@ -54,6 +55,9 @@ namespace const float FOCUSED_ICON_SATURATION_REF = 0.5f; const int DOUBLE_CLICK_SPEED = 500; //500 ms (double-click speed hardcoded to 400 ms in nux) + + const RawPixel WIDTH_PADDING = 25_em; + const RawPixel SCROLLBAR_WIDTH = 3_em; } NUX_IMPLEMENT_OBJECT_TYPE(ResultViewGrid); @@ -347,7 +351,7 @@ void ResultViewGrid::SizeReallocate() int width = (items_per_row * renderer_->width) + (padding*2) + ((items_per_row - 1) * horizontal_spacing); int geo_width = GetBaseWidth(); - int extra_width = geo_width - (width + 25-3); + int extra_width = geo_width - (width + WIDTH_PADDING.CP(scale_) - SCROLLBAR_WIDTH.CP(scale_)); if (items_per_row != 1) extra_horizontal_spacing_ = extra_width / (items_per_row - 1); @@ -1007,6 +1011,13 @@ ResultViewGrid::SetSelectedIndex(int index) } void +ResultViewGrid::UpdateScale(double scale) +{ + ResultView::UpdateScale(scale); + UpdateRenderTextures(); +} + +void ResultViewGrid::UpdateRenderTextures() { nux::Geometry root_geo(GetAbsoluteGeometry()); diff --git a/dash/ResultViewGrid.h b/dash/ResultViewGrid.h index bba997c0d..c039c2337 100644 --- a/dash/ResultViewGrid.h +++ b/dash/ResultViewGrid.h @@ -60,6 +60,8 @@ public: virtual void GetResultDimensions(int& rows, int& columns); + void UpdateScale(double scale); + protected: void MouseMove(int x, int y, int dx, int dy, unsigned long button_flags, unsigned long key_flags); void MouseClick(int x, int y, unsigned long button_flags, unsigned long key_flags); diff --git a/dash/ScopeBar.cpp b/dash/ScopeBar.cpp index 4dca163c0..13ab67bc6 100644 --- a/dash/ScopeBar.cpp +++ b/dash/ScopeBar.cpp @@ -27,6 +27,7 @@ #include "unity-shared/StaticCairoText.h" #include "unity-shared/CairoTexture.h" #include "unity-shared/GraphicsUtils.h" +#include "unity-shared/RawPixel.h" #include "unity-shared/UBusMessages.h" namespace unity @@ -38,7 +39,8 @@ namespace { // according to Q design the inner area of the scopebar should be 40px // (without any borders) -const int SCOPEBAR_HEIGHT = 41; +RawPixel const SCOPEBAR_HEIGHT = 41_em; +RawPixel const TRIANGLE_SIZE = 5_em; } @@ -46,11 +48,16 @@ NUX_IMPLEMENT_OBJECT_TYPE(ScopeBar); ScopeBar::ScopeBar() : nux::View(NUX_TRACKER_LOCATION) + , scale_(1.0) { SetupBackground(); SetupLayout(); } +ScopeBar::~ScopeBar() +{ +} + void ScopeBar::SetupBackground() { nux::ROPConfig rop; @@ -60,14 +67,28 @@ void ScopeBar::SetupBackground() bg_layer_.reset(new nux::ColorLayer(nux::Color(0.0f, 0.0f, 0.0f, 0.2f), true, rop)); } +void ScopeBar::UpdateScale(double scale) +{ + if (scale_ != scale) + { + scale_ = scale; + + SetMinimumHeight(SCOPEBAR_HEIGHT.CP(scale_)); + SetMaximumHeight(SCOPEBAR_HEIGHT.CP(scale_)); + + for (auto icon : icons_) + icon->UpdateScale(scale_); + } +} + void ScopeBar::SetupLayout() { layout_ = new nux::HLayout(NUX_TRACKER_LOCATION); layout_->SetContentDistribution(nux::MAJOR_POSITION_CENTER); SetLayout(layout_); - SetMinimumHeight(SCOPEBAR_HEIGHT); - SetMaximumHeight(SCOPEBAR_HEIGHT); + SetMinimumHeight(SCOPEBAR_HEIGHT.CP(scale_)); + SetMaximumHeight(SCOPEBAR_HEIGHT.CP(scale_)); } void ScopeBar::AddScope(Scope::Ptr const& scope) @@ -75,6 +96,7 @@ void ScopeBar::AddScope(Scope::Ptr const& scope) ScopeBarIcon* icon = new ScopeBarIcon(scope->id, scope->icon_hint); icon->SetVisible(scope->visible); + icon->UpdateScale(scale_); scope->visible.changed.connect([icon](bool visible) { icon->SetVisible(visible); } ); icons_.push_back(icon); layout_->AddView(icon, 0, nux::MINOR_POSITION_CENTER, nux::MINOR_SIZE_FIX); @@ -160,9 +182,9 @@ void ScopeBar::DrawContent(nux::GraphicsEngine& graphics_engine, bool force_draw { nux::Geometry const& geo = icon->GetGeometry(); int middle = geo.x + geo.width/2; - int size = 5; // Nux doesn't draw too well the small triangles, so let's draw a // bigger one and clip part of them using the "-1". + int size = TRIANGLE_SIZE.CP(scale_); int y = base.y - 1; nux::GetPainter().Draw2DTriangleColor(graphics_engine, diff --git a/dash/ScopeBar.h b/dash/ScopeBar.h index 2e64e0c1b..bdc2477c7 100644 --- a/dash/ScopeBar.h +++ b/dash/ScopeBar.h @@ -56,12 +56,15 @@ class ScopeBar : public nux::View, public unity::debug::Introspectable public: ScopeBar(); + ~ScopeBar(); void AddScope(Scope::Ptr const& scope); void Activate(std::string id); void ActivateNext(); void ActivatePrevious(); + void UpdateScale(double scale); + std::string GetActiveScopeId() const; sigc::signal<void, std::string const&> scope_activated; @@ -86,6 +89,8 @@ private: nux::HLayout* layout_; LayerPtr bg_layer_; + double scale_; + friend class TestScopeBar; }; diff --git a/dash/ScopeBarIcon.cpp b/dash/ScopeBarIcon.cpp index 7fdbbb05b..4cb81b7f5 100644 --- a/dash/ScopeBarIcon.cpp +++ b/dash/ScopeBarIcon.cpp @@ -17,6 +17,7 @@ */ #include "unity-shared/DashStyle.h" +#include "unity-shared/RawPixel.h" #include "ScopeBarIcon.h" #include "config.h" @@ -28,25 +29,25 @@ namespace dash namespace { -const int FOCUS_OVERLAY_HEIGHT = 44; -const int FOCUS_OVERLAY_WIDTH = 60; +RawPixel const FOCUS_OVERLAY_HEIGHT = 44_em; +RawPixel const FOCUS_OVERLAY_WIDTH = 60_em; +RawPixel const TEXTURE_SIZE = 24_em; +double const DEFAULT_SCALE = 1.0; } NUX_IMPLEMENT_OBJECT_TYPE(ScopeBarIcon); ScopeBarIcon::ScopeBarIcon(std::string id_, std::string icon_hint) - : IconTexture(icon_hint, 24) + : IconTexture(icon_hint, TEXTURE_SIZE) , id(id_) , active(false) , inactive_opacity_(0.4f) + , scale_(DEFAULT_SCALE) { - SetMinimumWidth(FOCUS_OVERLAY_WIDTH); - SetMaximumWidth(FOCUS_OVERLAY_WIDTH); - SetMinimumHeight(FOCUS_OVERLAY_HEIGHT); - SetMaximumHeight(FOCUS_OVERLAY_HEIGHT); + SetMinMaxSize(FOCUS_OVERLAY_WIDTH.CP(scale_), FOCUS_OVERLAY_HEIGHT.CP(scale_)); - focus_layer_.reset(Style::Instance().FocusOverlay(FOCUS_OVERLAY_WIDTH, FOCUS_OVERLAY_HEIGHT)); + focus_layer_.reset(Style::Instance().FocusOverlay(FOCUS_OVERLAY_WIDTH.CP(scale_), FOCUS_OVERLAY_HEIGHT.CP(scale_))); SetOpacity(inactive_opacity_); @@ -61,6 +62,22 @@ ScopeBarIcon::ScopeBarIcon(std::string id_, std::string icon_hint) ScopeBarIcon::~ScopeBarIcon() {} +void ScopeBarIcon::UpdateScale(double scale) +{ + if (scale_ != scale) + { + scale_ = scale; + int overlay_width = FOCUS_OVERLAY_WIDTH.CP(scale_); + int overlay_height = FOCUS_OVERLAY_HEIGHT.CP(scale_); + + SetMinMaxSize(overlay_width, overlay_height); + focus_layer_.reset(Style::Instance().FocusOverlay(overlay_width, overlay_height)); + + SetSize(TEXTURE_SIZE.CP(scale_)); + ReLoadIcon(); + } +} + void ScopeBarIcon::Draw(nux::GraphicsEngine& graphics_engine, bool force_draw) { nux::Geometry const& geo = GetGeometry(); diff --git a/dash/ScopeBarIcon.h b/dash/ScopeBarIcon.h index c3cba57af..f83afd73e 100644 --- a/dash/ScopeBarIcon.h +++ b/dash/ScopeBarIcon.h @@ -40,6 +40,8 @@ public: ScopeBarIcon(std::string id, std::string icon_hint); ~ScopeBarIcon(); + void UpdateScale(double scale); + nux::Property<std::string> id; nux::Property<bool> active; @@ -56,6 +58,8 @@ private: const float inactive_opacity_; LayerPtr focus_layer_; + + double scale_; }; } diff --git a/dash/ScopeView.cpp b/dash/ScopeView.cpp index a59d874b4..d765d8b2e 100755 --- a/dash/ScopeView.cpp +++ b/dash/ScopeView.cpp @@ -1,6 +1,6 @@ // -*- Mode: C++; indent-tabs-mode: nil; tab-width: 2 -*- /* - * Copyright (C) 2010, 2011 Canonical Ltd + * Copyright (C) 2010-2014 Canonical Ltd * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License version 3 as @@ -31,6 +31,7 @@ #include "unity-shared/UBusWrapper.h" #include "unity-shared/PlacesOverlayVScrollBar.h" #include "unity-shared/GraphicsUtils.h" +#include "unity-shared/RawPixel.h" #include "config.h" #include <glib/gi18n-lib.h> @@ -44,8 +45,10 @@ DECLARE_LOGGER(focus_logger, "unity.dash.scopeview.focus"); namespace { -const int CARD_VIEW_GAP_VERT = 24; // pixels -const int CARD_VIEW_GAP_HORIZ = 25; // pixels +const RawPixel CARD_VIEW_GAP_VERT = 24_em; // pixels +const RawPixel CARD_VIEW_GAP_HORIZ = 25_em; // pixels +const RawPixel FOCUSED_OFFSET = 30_em; +const double DEFAULT_SCALE = 1.0; } // This is so we can access some protected members in scrollview. @@ -157,6 +160,7 @@ ScopeView::ScopeView(Scope::Ptr const& scope, nux::Area* show_filters) , scope_connected_(scope ? scope->connected : false) , search_on_next_connect_(false) , current_focus_category_position_(-1) +, scale_(DEFAULT_SCALE) { SetupViews(show_filters); @@ -211,8 +215,8 @@ ScopeView::ScopeView(Scope::Ptr const& scope, nux::Area* show_filters) (expand_label && expand_label->HasKeyFocus())) { focused_pos.x += child->GetGeometry().x; - focused_pos.y += child->GetGeometry().y - 30; - focused_pos.height += 30; + focused_pos.y += child->GetGeometry().y - FOCUSED_OFFSET.CP(scale_); + focused_pos.height += FOCUSED_OFFSET.CP(scale_); scroll_view_->ScrollToPosition(focused_pos); break; } @@ -230,10 +234,7 @@ ScopeView::ScopeView(Scope::Ptr const& scope, nux::Area* show_filters) void ScopeView::SetupViews(nux::Area* show_filters) { - dash::Style& style = dash::Style::Instance(); - layout_ = new nux::HLayout(NUX_TRACKER_LOCATION); - layout_->SetSpaceBetweenChildren(style.GetSpaceBetweenScopeAndFilters()); scroll_view_ = new ScopeScrollView(new PlacesOverlayVScrollBar(NUX_TRACKER_LOCATION), NUX_TRACKER_LOCATION); @@ -261,18 +262,46 @@ void ScopeView::SetupViews(nux::Area* show_filters) fscroll_view_->SetLayout(fscroll_layout_); filter_bar_ = new FilterBar(); - int width = style.GetFilterBarWidth() + - style.GetFilterBarLeftPadding() + - style.GetFilterBarRightPadding(); - - fscroll_view_->SetMinimumWidth(width + style.GetFilterViewRightPadding()); - fscroll_view_->SetMaximumWidth(width + style.GetFilterViewRightPadding()); - filter_bar_->SetMinimumWidth(width); - filter_bar_->SetMaximumWidth(width); + AddChild(filter_bar_); fscroll_layout_->AddView(filter_bar_, 0); SetLayout(layout_); + + UpdateScopeViewSize(); +} + +void ScopeView::UpdateScopeViewSize() +{ + dash::Style const& style = dash::Style::Instance(); + + RawPixel const scope_filter_space = style.GetSpaceBetweenScopeAndFilters(); + RawPixel const right_padding = style.GetFilterViewRightPadding(); + RawPixel const filter_width = style.GetFilterBarWidth() + + style.GetFilterBarLeftPadding() + + style.GetFilterBarRightPadding(); + + layout_->SetSpaceBetweenChildren(scope_filter_space.CP(scale_)); + + fscroll_view_->SetMinimumWidth(filter_width.CP(scale_) + right_padding.CP(scale_)); + fscroll_view_->SetMaximumWidth(filter_width.CP(scale_) + right_padding.CP(scale_)); + filter_bar_->SetMinimumWidth(filter_width.CP(scale_)); + filter_bar_->SetMaximumWidth(filter_width.CP(scale_)); +} + +void ScopeView::UpdateScale(double scale) +{ + if (scale_ != scale) + { + scale_ = scale; + + UpdateScopeViewSize(); + + for (auto& group : category_views_) + group->UpdateScale(scale_); + + filter_bar_->UpdateScale(scale_); + } } void ScopeView::SetupCategories(Categories::Ptr const& categories) @@ -435,6 +464,7 @@ void ScopeView::OnCategoryAdded(Category const& category) group->SetIcon(icon_hint); group->SetExpanded(false); group->SetVisible(false); + group->UpdateScale(scale_); int view_index = category_order_.size(); auto find_view_index = std::find(category_order_.begin(), category_order_.end(), index); @@ -459,8 +489,8 @@ void ScopeView::OnCategoryAdded(Category const& category) { results_view = new ResultViewGrid(NUX_TRACKER_LOCATION); results_view->SetModelRenderer(new ResultRendererHorizontalTile(NUX_TRACKER_LOCATION)); - static_cast<ResultViewGrid*> (results_view)->horizontal_spacing = CARD_VIEW_GAP_HORIZ; - static_cast<ResultViewGrid*> (results_view)->vertical_spacing = CARD_VIEW_GAP_VERT; + static_cast<ResultViewGrid*> (results_view)->horizontal_spacing = CARD_VIEW_GAP_HORIZ.CP(scale_); + static_cast<ResultViewGrid*> (results_view)->vertical_spacing = CARD_VIEW_GAP_VERT.CP(scale_); } else { diff --git a/dash/ScopeView.h b/dash/ScopeView.h index f4c0b8b8c..2cebd1a86 100644 --- a/dash/ScopeView.h +++ b/dash/ScopeView.h @@ -1,6 +1,6 @@ // -*- Mode: C++; indent-tabs-mode: nil; tab-width: 2 -*- /* - * Copyright (C) 2010, 2011 Canonical Ltd + * Copyright (C) 2010-2014 Canonical Ltd * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License version 3 as @@ -86,6 +86,8 @@ public: std::vector<ResultViewTexture::Ptr> GetResultTextureContainers(); void RenderResultTexture(ResultViewTexture::Ptr const& result_texture); + void UpdateScale(double scale); + private: void SetupViews(nux::Area* show_filters); void SetupCategories(Categories::Ptr const& categories); @@ -128,6 +130,8 @@ private: void BuildPreview(std::string const& uri, Preview::Ptr model); + void UpdateScopeViewSize(); + virtual void Draw(nux::GraphicsEngine& gfx_context, bool force_draw); virtual void DrawContent(nux::GraphicsEngine& gfx_context, bool force_draw); @@ -186,6 +190,8 @@ private: int current_focus_category_position_; glib::Variant current_focus_variant_; + double scale_; + friend class TestScopeView; }; diff --git a/dash/StandaloneDash.cpp b/dash/StandaloneDash.cpp index 326e3a28a..39144ea0b 100644 --- a/dash/StandaloneDash.cpp +++ b/dash/StandaloneDash.cpp @@ -73,7 +73,7 @@ void TestRunner::Init () layout->AddView (view, 1, nux::MINOR_POSITION_CENTER); layout->SetMinMaxSize(WIDTH, HEIGHT); - view->AboutToShow(); + view->AboutToShow(0); nux::GetWindowThread()->SetLayout (layout); nux::GetWindowCompositor().SetKeyFocusArea(view->default_focus()); diff --git a/debian/changelog b/debian/changelog index a8e58d4c3..bafd83f22 100644 --- a/debian/changelog +++ b/debian/changelog @@ -1638,9 +1638,6 @@ unity (7.0.0daily13.05.31ubuntu.unity.next-0ubuntu1) raring; urgency=low unity (7.0.0daily13.05.08ubuntu.unity.next-0ubuntu1) raring; urgency=low * Automatic snapshot from revision 3317 (ubuntu-unity/next) - - -- Ubuntu daily release <ps-jenkins@lists.canonical.com> Wed, 08 May 2013 04:57:49 +0000 - unity (7.0.0daily13.05.01.1ubuntu.unity.next-0ubuntu1) raring; urgency=low [ Sebastien Bacher ] diff --git a/decorations/DecoratedWindow.cpp b/decorations/DecoratedWindow.cpp index 92f12d152..5909b06e0 100644 --- a/decorations/DecoratedWindow.cpp +++ b/decorations/DecoratedWindow.cpp @@ -129,7 +129,7 @@ void Window::Impl::UnsetExtents() if (win_->hasUnmapReference()) return; - CompWindowExtents empty(0, 0, 0, 0); + CompWindowExtents empty; if (win_->border() != empty || win_->input() != empty) win_->setWindowFrameExtents(&empty, &empty); @@ -415,6 +415,9 @@ unsigned Window::Impl::ShadowRadius() const void Window::Impl::RenderDecorationTexture(Side s, nux::Geometry const& geo) { + if (geo.width <= 0 || geo.height <= 0) + return; + auto& deco_tex = bg_textures_[unsigned(s)]; if (deco_tex.quad.box.width() != geo.width || deco_tex.quad.box.height() != geo.height) @@ -461,7 +464,7 @@ void Window::Impl::UpdateDecorationTextures() void Window::Impl::ComputeShadowQuads() { - if (!ShadowDecorated()) + if (last_shadow_rect_.isEmpty() && !ShadowDecorated()) return; const auto* texture = ShadowTexture(); @@ -555,19 +558,24 @@ void Window::Impl::ComputeShadowQuads() } } +void Window::Impl::Paint(GLMatrix const& transformation, + GLWindowPaintAttrib const& attrib, + CompRegion const& region, unsigned mask) +{ + if (dirty_geo_) + parent_->UpdateDecorationPosition(); +} + void Window::Impl::Draw(GLMatrix const& transformation, GLWindowPaintAttrib const& attrib, CompRegion const& region, unsigned mask) { - if (!ShadowDecorated()) + if (last_shadow_rect_.isEmpty()) return; auto const& clip_region = (mask & PAINT_WINDOW_TRANSFORMED_MASK) ? infiniteRegion : region; mask |= PAINT_WINDOW_BLEND_MASK; - if (dirty_geo_) - parent_->UpdateDecorationPosition(); - glwin_->vertexBuffer()->begin(); for (unsigned i = 0; i < shadow_quads_.size(); ++i) @@ -581,6 +589,9 @@ void Window::Impl::Draw(GLMatrix const& transformation, for (auto const& dtex : bg_textures_) { + if (!dtex) + continue; + glwin_->vertexBuffer()->begin(); glwin_->glAddGeometry({dtex.quad.matrix}, dtex.quad.box, clip_region); @@ -613,7 +624,7 @@ void Window::Impl::SetupAppMenu() sliding_layout->SetInputItem(nullptr); sliding_layout->mouse_owner = false; - if (!menu_manager->HasAppMenu()) + if (!menu_manager->HasAppMenu() || !Style::Get()->integrated_menus()) return; auto visibility_cb = sigc::hide(sigc::mem_fun(this, &Impl::UpdateAppMenuVisibility)); @@ -738,6 +749,12 @@ void Window::Draw(GLMatrix const& matrix, GLWindowPaintAttrib const& attrib, impl_->Draw(matrix, attrib, region, mask); } +void Window::Paint(GLMatrix const& matrix, GLWindowPaintAttrib const& attrib, + CompRegion const& region, unsigned mask) +{ + impl_->Paint(matrix, attrib, region, mask); +} + void Window::Undecorate() { impl_->Undecorate(); diff --git a/decorations/DecoratedWindow.h b/decorations/DecoratedWindow.h index a0739f4df..be49be600 100644 --- a/decorations/DecoratedWindow.h +++ b/decorations/DecoratedWindow.h @@ -51,6 +51,7 @@ public: void UpdateDecorationPositionDelayed(); void UpdateFrameRegion(CompRegion&); void UpdateOutputExtents(compiz::window::extents::Extents&); + void Paint(GLMatrix const&, GLWindowPaintAttrib const&, CompRegion const&, unsigned mask); void Draw(GLMatrix const&, GLWindowPaintAttrib const&, CompRegion const&, unsigned mask); protected: diff --git a/decorations/DecorationsManager.cpp b/decorations/DecorationsManager.cpp index d94d727f0..48f5cf006 100644 --- a/decorations/DecorationsManager.cpp +++ b/decorations/DecorationsManager.cpp @@ -209,6 +209,7 @@ Window::Ptr Manager::Impl::GetWindowByFrame(::Window xid) const bool Manager::Impl::HandleEventBefore(XEvent* event) { active_window_ = screen->activeWindow(); + switch (event->type) { case ClientMessage: diff --git a/decorations/DecorationsPriv.h b/decorations/DecorationsPriv.h index 69fe448ce..01f51f893 100644 --- a/decorations/DecorationsPriv.h +++ b/decorations/DecorationsPriv.h @@ -108,6 +108,7 @@ private: void ComputeShadowQuads(); void UpdateDecorationTextures(); void RenderDecorationTexture(Side, nux::Geometry const&); + void Paint(GLMatrix const&, GLWindowPaintAttrib const&, CompRegion const&, unsigned mask); void Draw(GLMatrix const&, GLWindowPaintAttrib const&, CompRegion const&, unsigned mask); friend class Window; diff --git a/decorations/DecorationsTitle.cpp b/decorations/DecorationsTitle.cpp index bc9eeff2a..454715af5 100644 --- a/decorations/DecorationsTitle.cpp +++ b/decorations/DecorationsTitle.cpp @@ -61,6 +61,12 @@ void Title::OnFontChanged(std::string const&) void Title::RenderTexture() { + if (!texture_size_.width || !texture_size_.height) + { + SetTexture(nullptr); + return; + } + auto state = focused() ? WidgetState::NORMAL : WidgetState::BACKDROP; cu::CairoContext text_ctx(texture_size_.width, texture_size_.height, scale()); Style::Get()->DrawTitle(text(), state, text_ctx, texture_size_.width / scale(), texture_size_.height / scale()); diff --git a/launcher/ApplicationLauncherIcon.cpp b/launcher/ApplicationLauncherIcon.cpp index 2e835dd6c..be7686e48 100644 --- a/launcher/ApplicationLauncherIcon.cpp +++ b/launcher/ApplicationLauncherIcon.cpp @@ -68,7 +68,6 @@ ApplicationLauncherIcon::ApplicationLauncherIcon(ApplicationPtr const& app) : SimpleLauncherIcon(IconType::APPLICATION) , _startup_notification_timestamp(0) , _last_scroll_timestamp(0) - , _last_scroll_direction(ScrollDirection::DOWN) , _progressive_scroll(0) , use_custom_bg_color_(false) , bg_color_(nux::color::White) @@ -722,6 +721,8 @@ void ApplicationLauncherIcon::EnsureWindowState() for (unsigned i = 0; i < monitors::MAX; i++) SetWindowVisibleOnMonitor(monitors[i], i); + + WindowsChanged.emit(); } void ApplicationLauncherIcon::UpdateDesktopQuickList() @@ -1276,19 +1277,17 @@ const std::set<std::string> ApplicationLauncherIcon::GetSupportedTypes() void PerformScrollUp(WindowList const& windows, unsigned int progressive_scroll) { - if (!progressive_scroll) - { - windows.at(1)->Focus(); - return; - } - else if (progressive_scroll == 1) + if (progressive_scroll == windows.size() - 1) { + //RestackAbove to preserve Global Stacking Order + WindowManager::Default().RestackBelow(windows.at(0)->window_id(), windows.at(1)->window_id()); + WindowManager::Default().RestackBelow(windows.at(1)->window_id(), windows.at(0)->window_id()); windows.back()->Focus(); return; } - WindowManager::Default().RestackBelow(windows.at(0)->window_id(), windows.at(windows.size() - progressive_scroll + 1)->window_id()); - windows.at(windows.size() - progressive_scroll + 1)->Focus(); + WindowManager::Default().RestackBelow(windows.at(0)->window_id(), windows.at(progressive_scroll + 1)->window_id()); + windows.at(progressive_scroll + 1)->Focus(); } void PerformScrollDown(WindowList const& windows, unsigned int progressive_scroll) @@ -1308,11 +1307,10 @@ void ApplicationLauncherIcon::PerformScroll(ScrollDirection direction, Time time { if (timestamp - _last_scroll_timestamp < 150) return; - else if (timestamp - _last_scroll_timestamp > 1500 || direction != _last_scroll_direction) + else if (timestamp - _last_scroll_timestamp > 1500) _progressive_scroll = 0; _last_scroll_timestamp = timestamp; - _last_scroll_direction = direction; auto const& windows = GetWindowsOnCurrentDesktopInStackingOrder(); @@ -1331,7 +1329,11 @@ void ApplicationLauncherIcon::PerformScroll(ScrollDirection direction, Time time if (windows.size() <= 1) return; - ++_progressive_scroll; + if (direction == ScrollDirection::DOWN) + ++_progressive_scroll; + else + //--_progressive_scroll; but roll to the top of windows + _progressive_scroll += windows.size() - 1; _progressive_scroll %= windows.size(); switch(direction) diff --git a/launcher/ApplicationLauncherIcon.h b/launcher/ApplicationLauncherIcon.h index 601674b55..e7a26fed7 100644 --- a/launcher/ApplicationLauncherIcon.h +++ b/launcher/ApplicationLauncherIcon.h @@ -139,7 +139,6 @@ private: std::string _remote_uri; Time _startup_notification_timestamp; Time _last_scroll_timestamp; - ScrollDirection _last_scroll_direction; unsigned int _progressive_scroll; std::set<std::string> _supported_types; std::vector<glib::Object<DbusmenuMenuitem>> _menu_items; diff --git a/launcher/LauncherIcon.cpp b/launcher/LauncherIcon.cpp index 163f6c527..a83f27d4d 100644 --- a/launcher/LauncherIcon.cpp +++ b/launcher/LauncherIcon.cpp @@ -879,6 +879,8 @@ void LauncherIcon::SetQuirk(LauncherIcon::Quirk quirk, bool value, int monitor) if (quirk == Quirk::VISIBLE) visibility_changed.emit(monitor); + + QuirksChanged.emit(); } void LauncherIcon::FullyAnimateQuirkDelayed(guint ms, LauncherIcon::Quirk quirk, int monitor) diff --git a/launcher/LauncherIcon.h b/launcher/LauncherIcon.h index 934cc15c2..712af8444 100644 --- a/launcher/LauncherIcon.h +++ b/launcher/LauncherIcon.h @@ -139,6 +139,9 @@ public: void SkipQuirkAnimation(Quirk quirk, int monitor = -1); + sigc::signal<void> QuirksChanged; + sigc::signal<void> WindowsChanged; + IconType GetIconType() const; virtual nux::Color BackgroundColor() const; diff --git a/launcher/SwitcherController.cpp b/launcher/SwitcherController.cpp index e1470d4ec..8420f1dfa 100644 --- a/launcher/SwitcherController.cpp +++ b/launcher/SwitcherController.cpp @@ -69,7 +69,9 @@ namespace switcher { Controller::Controller(WindowCreator const& create_window) - : detail_mode([this] { return detail_mode_; }) + : detail([this] { return impl_->model_ && impl_->model_->detail_selection(); }, + [this] (bool d) { if (impl_->model_) { impl_->model_->detail_selection = d; } return false; }) + , detail_mode([this] { return detail_mode_; }) , timeout_length(0) , detail_on_timeout(true) , detail_timeout_length(500) @@ -133,8 +135,7 @@ void Controller::Impl::StartDetailMode() { if (obj_->visible_) { - if (IsDetailViewShown() && - HasNextDetailRow()) + if (obj_->detail() && HasNextDetailRow()) { NextDetailRow(); } @@ -149,8 +150,7 @@ void Controller::Impl::StopDetailMode() { if (obj_->visible_) { - if (IsDetailViewShown() && - HasPrevDetailRow()) + if (obj_->detail() && HasPrevDetailRow()) { PrevDetailRow(); } @@ -176,11 +176,6 @@ SwitcherView::Ptr Controller::GetView() const return impl_->GetView(); } -bool Controller::IsDetailViewShown() -{ - return impl_->IsDetailViewShown(); -} - void Controller::SetDetail(bool value, unsigned int min_windows) { impl_->SetDetail(value, min_windows); @@ -201,16 +196,11 @@ void Controller::PrevDetail() impl_->PrevDetail(); } -LayoutWindow::Vector Controller::ExternalRenderTargets() +LayoutWindow::Vector const& Controller::ExternalRenderTargets() const { return impl_->ExternalRenderTargets(); } -guint Controller::GetSwitcherInputWindowId() const -{ - return impl_->GetSwitcherInputWindowId(); -} - bool Controller::IsShowDesktopDisabled() const { return show_desktop_disabled_; @@ -251,11 +241,6 @@ sigc::connection Controller::ConnectToViewBuilt(const sigc::slot<void> &f) return impl_->view_built.connect(f); } -void Controller::SetDetailOnTimeout(bool timeout) -{ - detail_on_timeout = timeout; -} - double Controller::Opacity() const { if (!impl_->view_window_) @@ -512,12 +497,16 @@ void Controller::Impl::DetailHide() { // FIXME We need to refactor SwitcherModel so we can add/remove icons without causing // a crash. If you remove the last application in the list it crashes. + obj_->detail.changed.emit(false); model_->detail_selection = false; Hide(false); } void Controller::Impl::HideWindow() { + if (model_->detail_selection()) + obj_->detail.changed.emit(false); + main_layout_->RemoveChildObject(view_.GetPointer()); view_window_->SetOpacity(0.0f); @@ -591,20 +580,17 @@ SwitcherView::Ptr Controller::Impl::GetView() const return view_; } -bool Controller::Impl::IsDetailViewShown() -{ - return model_ && model_->detail_selection(); -} - void Controller::Impl::SetDetail(bool value, unsigned int min_windows) { if (value && model_->Selection()->AllowDetailViewInSwitcher() && model_->DetailXids().size() >= min_windows) { model_->detail_selection = true; obj_->detail_mode_ = DetailMode::TAB_NEXT_WINDOW; + obj_->detail.changed.emit(true); } else { + obj_->detail.changed.emit(false); model_->detail_selection = false; } } @@ -673,22 +659,17 @@ bool Controller::Impl::HasPrevDetailRow() const return model_->HasPrevDetailRow(); } -LayoutWindow::Vector Controller::Impl::ExternalRenderTargets() +LayoutWindow::Vector const& Controller::Impl::ExternalRenderTargets() const { if (!view_) { - LayoutWindow::Vector result; - return result; + static LayoutWindow::Vector empty_list; + return empty_list; } - return view_->ExternalTargets(); -} -guint Controller::Impl::GetSwitcherInputWindowId() const -{ - return view_window_->GetInputWindowId(); + return view_->ExternalTargets(); } - Selection Controller::Impl::GetCurrentSelection() const { AbstractLauncherIcon::Ptr application; @@ -712,7 +693,6 @@ Selection Controller::Impl::GetCurrentSelection() const return {application, window}; } - void Controller::Impl::SelectFirstItem() { if (!model_) @@ -743,7 +723,7 @@ void Controller::Impl::SelectFirstItem() for (auto& window : first->Windows()) { Window xid = window->window_id(); - + if (model_->only_detail_on_viewport && !wm.IsWindowOnCurrentDesktop(xid)) continue; diff --git a/launcher/SwitcherController.h b/launcher/SwitcherController.h index 6ad903914..94396072e 100644 --- a/launcher/SwitcherController.h +++ b/launcher/SwitcherController.h @@ -107,9 +107,7 @@ public: nux::ObjectPtr<SwitcherView> GetView() const; - ui::LayoutWindow::Vector ExternalRenderTargets(); - - guint GetSwitcherInputWindowId() const; + ui::LayoutWindow::Vector const& ExternalRenderTargets() const; bool IsShowDesktopDisabled() const; void SetShowDesktopDisabled(bool disabled); @@ -123,12 +121,12 @@ public: Selection GetCurrentSelection() const; sigc::connection ConnectToViewBuilt(sigc::slot<void> const&); - void SetDetailOnTimeout(bool timeout); // Introspectable methods std::string GetName() const; void AddProperties(debug::IntrospectionData&); + nux::RWProperty<bool> detail; nux::ROProperty<DetailMode> detail_mode; nux::Property<int> timeout_length; nux::Property<bool> detail_on_timeout; diff --git a/launcher/SwitcherControllerImpl.h b/launcher/SwitcherControllerImpl.h index 2bba90e99..783257a2a 100644 --- a/launcher/SwitcherControllerImpl.h +++ b/launcher/SwitcherControllerImpl.h @@ -71,10 +71,7 @@ struct Controller::Impl : public sigc::trackable void SelectFirstItem(); virtual SwitcherView::Ptr GetView() const; - - ui::LayoutWindow::Vector ExternalRenderTargets(); - - guint GetSwitcherInputWindowId() const; + ui::LayoutWindow::Vector const& ExternalRenderTargets() const; int StartIndex() const; Selection GetCurrentSelection() const; diff --git a/launcher/SwitcherView.cpp b/launcher/SwitcherView.cpp index 7245bbf82..b0049f4fc 100644 --- a/launcher/SwitcherView.cpp +++ b/launcher/SwitcherView.cpp @@ -141,7 +141,7 @@ debug::Introspectable::IntrospectableList SwitcherView::GetIntrospectableChildre return introspection_results; } -LayoutWindow::Vector SwitcherView::ExternalTargets () +LayoutWindow::Vector const& SwitcherView::ExternalTargets() const { return render_targets_; } @@ -588,8 +588,8 @@ void SwitcherView::ResizeRenderTargets(nux::Geometry const& layout_geo, float pr for (LayoutWindow::Ptr const& win : render_targets_) { - auto final_geo = win->result; - win->result = final_geo * progress; + win->scale *= progress; + win->result = win->result * progress; win->result.x += layout_abs_center.x; win->result.y += layout_abs_center.y; } @@ -934,7 +934,7 @@ void SwitcherView::DrawOverlay(nux::GraphicsEngine& GfxContext, bool force_draw, if (render_boxes) { float val = 0.1f; - for (LayoutWindow::Ptr const& layout : ExternalTargets()) + for (LayoutWindow::Ptr const& layout : render_targets_) { gPainter.Paint2DQuadColor(GfxContext, layout->result, nux::Color(val, val, val ,val)); val += 0.1f; diff --git a/launcher/SwitcherView.h b/launcher/SwitcherView.h index 2d09e01c3..3e72ccffe 100644 --- a/launcher/SwitcherView.h +++ b/launcher/SwitcherView.h @@ -51,7 +51,7 @@ public: SwitcherView(); - ui::LayoutWindow::Vector ExternalTargets(); + ui::LayoutWindow::Vector const& ExternalTargets() const; void SetModel(SwitcherModel::Ptr model); SwitcherModel::Ptr GetModel(); diff --git a/panel/PanelMenuView.cpp b/panel/PanelMenuView.cpp index a30b2af68..130e60434 100644 --- a/panel/PanelMenuView.cpp +++ b/panel/PanelMenuView.cpp @@ -131,6 +131,7 @@ void PanelMenuView::SetupPanelMenuViewSignals() auto const& deco_style = decoration::Style::Get(); lim_changed_connection_ = deco_style->integrated_menus.changed.connect([this] (bool lim) { integrated_menus_ = lim; + new_application_ = nullptr; if (!integrated_menus_) { auto mouse = nux::GetGraphicsDisplay()->GetMouseScreenCoord(); @@ -693,22 +694,30 @@ std::string PanelMenuView::GetActiveViewName(bool use_appname) const if (BAMF_IS_WINDOW(window)) { BamfView *view = reinterpret_cast<BamfView*>(window); - std::vector<Window> const& our_xids = nux::XInputWindow::NativeHandleList(); Window window_xid = bamf_window_get_xid(window); - if (std::find(our_xids.begin(), our_xids.end(), window_xid) != our_xids.end()) + if (bamf_window_get_window_type(window) == BAMF_WINDOW_DOCK) { - /* If the active window is an unity window, we need to fallback to the - * top one, anyway we should always avoid to focus unity internal windows */ - BamfWindow* top_win = GetBamfWindowForXid(GetTopWindow()); + auto panel = const_cast<PanelMenuView*>(this)->GetTopLevelViewWindow(); + if (static_cast<nux::BaseWindow*>(panel)->GetInputWindowId() == window_xid) + return desktop_name_; - if (top_win && top_win != window) - { - window = top_win; - } - else + std::vector<Window> const& our_xids = nux::XInputWindow::NativeHandleList(); + + if (std::find(our_xids.begin(), our_xids.end(), window_xid) != our_xids.end()) { - return ""; + /* If the active window is an unity window, we need to fallback to the + * top one, anyway we should always avoid to focus unity internal windows */ + BamfWindow* top_win = GetBamfWindowForXid(GetTopWindow()); + + if (top_win && top_win != window) + { + window = top_win; + } + else + { + return ""; + } } } @@ -718,7 +727,7 @@ std::string PanelMenuView::GetActiveViewName(bool use_appname) const } else if (!IsValidWindow(window_xid)) { - return ""; + return ""; } if (WindowManager::Default().IsWindowMaximized(window_xid) && !use_appname) @@ -920,11 +929,16 @@ void PanelMenuView::NotifyAllMenusClosed() { last_active_view_ = nullptr; - if (integrated_menus_ && is_maximized_) + if (!integrated_menus_ || is_maximized_) { auto mouse = nux::GetGraphicsDisplay()->GetMouseScreenCoord(); - is_inside_ = GetAbsoluteGeometry().IsInside(mouse); - FullRedraw(); + bool inside = GetAbsoluteGeometry().IsInside(mouse); + + if (is_inside_ != inside) + { + is_inside_ = inside; + QueueDraw(); + } } } @@ -973,7 +987,7 @@ void PanelMenuView::OnViewOpened(BamfMatcher *matcher, BamfView *view) void PanelMenuView::OnApplicationClosed(BamfApplication* app) { - if (BAMF_IS_APPLICATION(app)) + if (BAMF_IS_APPLICATION(app) && !integrated_menus_) { if (std::find(new_apps_.begin(), new_apps_.end(), app) != new_apps_.end()) { @@ -1021,10 +1035,12 @@ void PanelMenuView::OnActiveAppChanged(BamfMatcher *matcher, { if (BAMF_IS_APPLICATION(new_app)) { - app_name_changed_signal_.Disconnect(); app_name_changed_signal_.Connect(BAMF_VIEW(new_app), "name-changed", sigc::mem_fun(this, &PanelMenuView::OnNameChanged)); + if (integrated_menus_) + return; + if (std::find(new_apps_.begin(), new_apps_.end(), new_app) != new_apps_.end()) { if (new_application_ != new_app) @@ -1144,6 +1160,11 @@ void PanelMenuView::OnWindowMinimized(Window xid) if (Refresh()) QueueDraw(); } + else if (integrated_menus_ && window_buttons_->controlled_window == xid) + { + if (Refresh()) + QueueDraw(); + } } void PanelMenuView::OnWindowUnminimized(Window xid) @@ -1156,6 +1177,11 @@ void PanelMenuView::OnWindowUnminimized(Window xid) if (Refresh()) QueueDraw(); } + else if (integrated_menus_ && IsWindowUnderOurControl(xid)) + { + if (Refresh()) + QueueDraw(); + } } void PanelMenuView::OnWindowUnmapped(Window xid) @@ -1169,6 +1195,11 @@ void PanelMenuView::OnWindowUnmapped(Window xid) if (Refresh()) QueueDraw(); } + else if (integrated_menus_ && window_buttons_->controlled_window == xid) + { + if (Refresh()) + QueueDraw(); + } } void PanelMenuView::OnWindowMapped(Window xid) @@ -1199,6 +1230,11 @@ void PanelMenuView::OnWindowMaximized(Window xid) if (Refresh()) FullRedraw(); } + else if (integrated_menus_ && IsWindowUnderOurControl(xid)) + { + if (Refresh()) + QueueDraw(); + } } void PanelMenuView::OnWindowRestored(Window xid) @@ -1213,6 +1249,11 @@ void PanelMenuView::OnWindowRestored(Window xid) if (Refresh()) FullRedraw(); } + else if (integrated_menus_ && window_buttons_->controlled_window == xid) + { + if (Refresh()) + QueueDraw(); + } } bool PanelMenuView::UpdateActiveWindowPosition() diff --git a/plugins/unityshell/src/unity-launcher-icon-accessible.cpp b/plugins/unityshell/src/unity-launcher-icon-accessible.cpp index 66643eadf..3284287bf 100644 --- a/plugins/unityshell/src/unity-launcher-icon-accessible.cpp +++ b/plugins/unityshell/src/unity-launcher-icon-accessible.cpp @@ -41,6 +41,8 @@ * */ +#include <glib/gi18n.h> + #include "unity-launcher-icon-accessible.h" #include "unity-launcher-accessible.h" #include "Launcher.h" @@ -111,6 +113,9 @@ struct _UnityLauncherIconAccessiblePrivate guint on_parent_change_id; guint on_parent_selection_change_id; guint on_parent_focus_event_id; + + /* A textual representation of the icon's name and its quirks */ + gchar* name; }; static void @@ -138,6 +143,7 @@ unity_launcher_icon_accessible_init(UnityLauncherIconAccessible* launcher_icon_a UNITY_LAUNCHER_ICON_ACCESSIBLE_GET_PRIVATE(launcher_icon_accessible); launcher_icon_accessible->priv = priv; + launcher_icon_accessible->priv->name = NULL; } static void @@ -160,6 +166,12 @@ unity_launcher_icon_accessible_dispose(GObject* object) if (self->priv->on_parent_change_id != 0) g_signal_handler_disconnect(object, self->priv->on_parent_change_id); + if (self->priv->name != NULL) + { + g_free(self->priv->name); + self->priv->name = NULL; + } + G_OBJECT_CLASS(unity_launcher_icon_accessible_parent_class)->dispose(object); } @@ -213,13 +225,23 @@ on_parent_change_cb(gchar* property, } static void +on_quirks_change_cb(UnityLauncherIconAccessible* self) +{ + g_object_notify(G_OBJECT(self), "accessible-name"); +} + +static void unity_launcher_icon_accessible_initialize(AtkObject* accessible, gpointer data) { UnityLauncherIconAccessible* self = NULL; + nux::Object* object = NULL; + LauncherIcon* icon = NULL; ATK_OBJECT_CLASS(unity_launcher_icon_accessible_parent_class)->initialize(accessible, data); self = UNITY_LAUNCHER_ICON_ACCESSIBLE(accessible); + object = (nux::Object*) data; + icon = dynamic_cast<LauncherIcon*>(object); accessible->role = ATK_ROLE_PUSH_BUTTON; @@ -230,30 +252,60 @@ unity_launcher_icon_accessible_initialize(AtkObject* accessible, self->priv->on_parent_change_id = g_signal_connect(accessible, "notify::accessible-parent", G_CALLBACK(on_parent_change_cb), self); + + icon->QuirksChanged.connect(sigc::bind(sigc::ptr_fun(on_quirks_change_cb), self)); + icon->WindowsChanged.connect(sigc::bind(sigc::ptr_fun(on_quirks_change_cb), self)); } static const gchar* unity_launcher_icon_accessible_get_name(AtkObject* obj) { - const gchar* name; + UnityLauncherIconAccessible* self = NULL; g_return_val_if_fail(UNITY_IS_LAUNCHER_ICON_ACCESSIBLE(obj), NULL); + self = UNITY_LAUNCHER_ICON_ACCESSIBLE(obj); + + if (self->priv->name != NULL) + { + g_free(self->priv->name); + self->priv->name = NULL; + } - name = ATK_OBJECT_CLASS(unity_launcher_icon_accessible_parent_class)->get_name(obj); - if (name == NULL) + self->priv->name = g_strdup(ATK_OBJECT_CLASS(unity_launcher_icon_accessible_parent_class)->get_name(obj)); + if (self->priv->name == NULL) { LauncherIcon* icon = NULL; + Launcher* launcher = NULL; icon = dynamic_cast<LauncherIcon*>(nux_object_accessible_get_object(NUX_OBJECT_ACCESSIBLE(obj))); + launcher = dynamic_cast<Launcher*>(nux_object_accessible_get_object(NUX_OBJECT_ACCESSIBLE(atk_object_get_parent(obj)))); if (icon == NULL) /* State is defunct */ - name = NULL; + self->priv->name = NULL; else - name = icon->tooltip_text().c_str(); + { + /* We do not want to present the running state of apps in the switcher, + * Because showing in the switcher implies they are running + */ + if (launcher == NULL) + self->priv->name = g_strdup(icon->tooltip_text().c_str()); + else + { + if (icon->GetQuirk(LauncherIcon::Quirk::RUNNING)) + if (icon->Windows().size() > 0) + self->priv->name = g_strdup_printf(_("%s: running: %zu windows open"), + icon->tooltip_text().c_str(), + icon->Windows().size()); + else + self->priv->name = g_strdup_printf(_("%s: running"), icon->tooltip_text().c_str()); + else + self->priv->name = g_strdup(icon->tooltip_text().c_str()); + } + } } - return name; + return self->priv->name; } static AtkStateSet* diff --git a/plugins/unityshell/src/unityshell.cpp b/plugins/unityshell/src/unityshell.cpp index 4ec6286ec..1157ddb25 100644 --- a/plugins/unityshell/src/unityshell.cpp +++ b/plugins/unityshell/src/unityshell.cpp @@ -52,6 +52,7 @@ #include "launcher/XdndStartStopNotifierImp.h" #include "CompizShortcutModeller.h" #include "GnomeKeyGrabber.h" +#include "RawPixel.h" #include "decorations/DecorationsDataPool.h" #include "decorations/DecorationsManager.h" @@ -137,7 +138,10 @@ const unsigned int SCROLL_DOWN_BUTTON = 6; const unsigned int SCROLL_UP_BUTTON = 7; const int MAX_BUFFER_AGE = 11; const int FRAMES_TO_REDRAW_ON_RESUME = 10; +const RawPixel SCALE_PADDING = 40_em; +const RawPixel SCALE_SPACING = 20_em; const std::string RELAYOUT_TIMEOUT = "relayout-timeout"; +const std::string FIRST_RUN_STAMP = "first_run.stamp"; } // namespace local } // anon namespace @@ -267,6 +271,7 @@ UnityScreen::UnityScreen(CompScreen* screen) ScreenInterface::setHandler(screen); CompositeScreenInterface::setHandler(cScreen); GLScreenInterface::setHandler(gScreen); + ScaleScreenInterface::setHandler(sScreen); PluginAdapter::Initialize(screen); AddChild(&WindowManager::Default()); @@ -388,9 +393,6 @@ UnityScreen::UnityScreen(CompScreen* screen) ubus_manager_.RegisterInterest(UBUS_LAUNCHER_END_KEY_SWITCHER, sigc::mem_fun(this, &UnityScreen::OnLauncherEndKeyNav)); - ubus_manager_.RegisterInterest(UBUS_SWITCHER_END, - sigc::mem_fun(this, &UnityScreen::OnSwitcherEnd)); - auto init_plugins_cb = sigc::mem_fun(this, &UnityScreen::initPluginActions); sources_.Add(std::make_shared<glib::Idle>(init_plugins_cb, glib::Source::Priority::DEFAULT)); @@ -528,7 +530,11 @@ void UnityScreen::OnInitiateSpread() }); for (auto const& swin : sScreen->getWindows()) - UnityWindow::get(swin->window)->OnInitiateSpread(); + { + auto* uwin = UnityWindow::get(swin->window); + fake_decorated_windows_.insert(uwin); + uwin->OnInitiateSpread(); + } } void UnityScreen::OnTerminateSpread() @@ -537,6 +543,8 @@ void UnityScreen::OnTerminateSpread() for (auto const& swin : sScreen->getWindows()) UnityWindow::get(swin->window)->OnTerminateSpread(); + + fake_decorated_windows_.clear(); } void UnityScreen::DamagePanelShadow() @@ -871,18 +879,17 @@ void UnityScreen::paintDisplay() } } - if (switcher_controller_->Opacity() > 0.0f) + if (switcher_controller_->detail()) { - LayoutWindow::Vector const& targets = switcher_controller_->ExternalRenderTargets(); + auto const& targets = switcher_controller_->ExternalRenderTargets(); for (LayoutWindow::Ptr const& target : targets) { if (CompWindow* window = screen->findWindow(target->xid)) { UnityWindow *unity_window = UnityWindow::get(window); - double scale = target->result.width / static_cast<double>(target->geo.width); double parent_alpha = switcher_controller_->Opacity(); - unity_window->paintThumbnail(target->result, target->alpha, parent_alpha, scale, + unity_window->paintThumbnail(target->result, target->alpha, parent_alpha, target->scale, target->decoration_height, target->selected); } } @@ -1705,7 +1712,7 @@ void UnityScreen::handleEvent(XEvent* event) if (CompWindow *w = screen->findWindow(sScreen->getSelectedWindow())) skip_other_plugins = UnityWindow::get(w)->handleEvent(event); } - else if (switcher_controller_->IsDetailViewShown()) + else if (switcher_controller_->detail()) { Window win = switcher_controller_->GetCurrentSelection().window_; CompWindow* w = screen->findWindow(win); @@ -1736,7 +1743,7 @@ void UnityScreen::handleEvent(XEvent* event) skip_other_plugins = UnityWindow::get(w)->handleEvent(event); } } - else if (switcher_controller_->IsDetailViewShown()) + else if (switcher_controller_->detail()) { Window win = switcher_controller_->GetCurrentSelection().window_; CompWindow* w = screen->findWindow(win); @@ -1747,8 +1754,11 @@ void UnityScreen::handleEvent(XEvent* event) if (dash_controller_->IsVisible()) { + int panel_height = panel_style_.PanelHeight(dash_controller_->Monitor()); nux::Point pt(event->xbutton.x_root, event->xbutton.y_root); - nux::Geometry const& dash_geo = dash_controller_->GetInputWindowGeometry(); + nux::Geometry const& dash = dash_controller_->GetInputWindowGeometry(); + nux::Geometry const& dash_geo = nux::Geometry(dash.x, dash.y, dash.width, + dash.height + panel_height); Window dash_xid = dash_controller_->window()->GetInputWindowId(); Window top_xid = wm.GetTopWindowAbove(dash_xid); @@ -1798,7 +1808,7 @@ void UnityScreen::handleEvent(XEvent* event) break; case ButtonRelease: - if (switcher_controller_->IsDetailViewShown()) + if (switcher_controller_->detail()) { Window win = switcher_controller_->GetCurrentSelection().window_; CompWindow* w = screen->findWindow(win); @@ -2305,13 +2315,13 @@ bool UnityScreen::altTabNextWindowInitiate(CompAction* action, CompAction::State switcher_controller_->Select((switcher_controller_->StartIndex())); // always select the current application switcher_controller_->InitiateDetail(); } - else if (switcher_controller_->IsDetailViewShown()) + else if (switcher_controller_->detail()) { switcher_controller_->NextDetail(); } else { - switcher_controller_->SetDetail(true); + switcher_controller_->detail = true; } action->setState(action->state() | CompAction::StateTermKey); @@ -2406,13 +2416,27 @@ void UnityScreen::OnLauncherEndKeyNav(GVariant* data) PluginAdapter::Default().RestoreInputFocus(); } -void UnityScreen::OnSwitcherEnd(GVariant* data) +void UnityScreen::OnSwitcherDetailChanged(bool detail) { - for (UnityWindow* uwin : fake_decorated_windows_) + if (detail) { - uwin->close_icon_state_ = decoration::WidgetState::NORMAL; - uwin->middle_clicked_ = false; - uwin->CleanupCachedTextures(); + for (LayoutWindow::Ptr const& target : switcher_controller_->ExternalRenderTargets()) + { + if (CompWindow* window = screen->findWindow(target->xid)) + { + auto* uwin = UnityWindow::get(window); + uwin->close_icon_state_ = decoration::WidgetState::NORMAL; + uwin->middle_clicked_ = false; + fake_decorated_windows_.insert(uwin); + } + } + } + else + { + for (UnityWindow* uwin : fake_decorated_windows_) + uwin->CleanupCachedTextures(); + + fake_decorated_windows_.clear(); } } @@ -2874,7 +2898,9 @@ bool UnityWindow::glPaint(const GLWindowPaintAttrib& attrib, wAttrib.brightness *= 0.75f; } - return gWindow->glPaint(wAttrib, matrix, region, mask); + bool ret = gWindow->glPaint(wAttrib, matrix, region, mask); + deco_win_->Paint(matrix, wAttrib, region, mask); + return ret; } /* handle window painting in an opengl context @@ -3487,7 +3513,7 @@ void UnityScreen::optionChanged(CompOption* opt, UnityshellOptions::Options num) launcher_options->super_tap_duration = optionGetDashTapDuration(); break; case UnityshellOptions::AltTabTimeout: - switcher_controller_->SetDetailOnTimeout(optionGetAltTabTimeout()); + switcher_controller_->detail_on_timeout = optionGetAltTabTimeout(); case UnityshellOptions::AltTabBiasViewport: PluginAdapter::Default().bias_active_to_viewport = optionGetAltTabBiasViewport(); break; @@ -3608,7 +3634,77 @@ void UnityScreen::outputChangeNotify() ScheduleRelayout(500); } -void UnityScreen::OnDashRealized () +bool UnityScreen::layoutSlotsAndAssignWindows() +{ + auto const& scaled_windows = sScreen->getWindows(); + + for (auto const& output : screen->outputDevs()) + { + ui::LayoutWindow::Vector layout_windows; + int monitor = UScreen::GetDefault()->GetMonitorAtPosition(output.centerX(), output.centerY()); + double monitor_scale = unity_settings_.em(monitor)->DPIScale(); + + for (ScaleWindow *sw : scaled_windows) + { + if (sw->window->outputDevice() == static_cast<int>(output.id())) + { + UnityWindow::get(sw->window)->deco_win_->scaled = true; + layout_windows.emplace_back(std::make_shared<LayoutWindow>(sw->window->id())); + } + } + + auto max_bounds = NuxGeometryFromCompRect(output.workArea()); + + if (launcher_controller_->options()->hide_mode != LAUNCHER_HIDE_NEVER) + { + int monitor_width = unity_settings_.LauncherWidth(monitor); + max_bounds.x += monitor_width; + max_bounds.width -= monitor_width; + } + + nux::Geometry final_bounds; + ui::LayoutSystem layout; + layout.max_row_height = max_bounds.height; + layout.spacing = local::SCALE_SPACING.CP(monitor_scale); + int padding = local::SCALE_PADDING.CP(monitor_scale); + max_bounds.Expand(-padding, -padding); + layout.LayoutWindows(layout_windows, max_bounds, final_bounds); + + auto lw_it = layout_windows.begin(); + for (auto const& sw : scaled_windows) + { + if (lw_it == layout_windows.end()) + break; + + LayoutWindow::Ptr const& lw = *lw_it; + + if (sw->window->id() != lw->xid) + continue; + + ScaleSlot slot(CompRectFromNuxGeo(lw->result)); + slot.scale = lw->scale; + + float sx = lw->geo.width * slot.scale; + float sy = lw->geo.height * slot.scale; + float cx = (slot.x1() + slot.x2()) / 2; + float cy = (slot.y1() + slot.y2()) / 2; + + CompWindow *w = sw->window; + cx += w->input().left * slot.scale; + cy += w->input().top * slot.scale; + + slot.setGeometry(cx - sx / 2, cy - sy / 2, sx, sy); + slot.filled = true; + + sw->setSlot(slot); + ++lw_it; + } + } + + return true; +} + +void UnityScreen::OnDashRealized() { /* stack any windows named "onboard" above us */ for (CompWindow *w : screen->windows ()) @@ -3638,6 +3734,7 @@ void UnityScreen::initLauncher() AddChild(launcher_controller_.get()); switcher_controller_ = std::make_shared<switcher::Controller>(); + switcher_controller_->detail.changed.connect(sigc::mem_fun(this, &UnityScreen::OnSwitcherDetailChanged)); AddChild(switcher_controller_.get()); LOG_INFO(logger) << "initLauncher-Launcher " << timer.ElapsedSeconds() << "s"; @@ -3668,6 +3765,7 @@ void UnityScreen::initLauncher() auto shortcuts_modeller = std::make_shared<shortcut::CompizModeller>(); shortcut_controller_ = std::make_shared<shortcut::Controller>(base_window_raiser, shortcuts_modeller); AddChild(shortcut_controller_.get()); + ShowFirstRunHints(); // Setup Session Controller auto manager = std::make_shared<session::GnomeManager>(); @@ -3754,6 +3852,41 @@ CompAction::Vector& UnityScreen::getActions() return menus_->KeyGrabber()->GetActions(); } +void UnityScreen::ShowFirstRunHints() +{ + sources_.AddTimeoutSeconds(1, [this] { + auto const& cache_dir = glib::gchar_to_string(g_get_user_cache_dir())+"/unity/"; + if (!g_file_test((cache_dir+local::FIRST_RUN_STAMP).c_str(), G_FILE_TEST_EXISTS)) + { + // We focus the panel, so the shortcut hint will be hidden at first user input + auto const& panels = panel_controller_->panels(); + if (!panels.empty()) + { + auto panel_win = static_cast<nux::BaseWindow*>(panels.front()->GetTopLevelViewWindow()); + SaveInputThenFocus(panel_win->GetInputWindowId()); + } + shortcut_controller_->first_run = true; + shortcut_controller_->Show(); + + if (g_mkdir_with_parents(cache_dir.c_str(), 0700) >= 0) + { + glib::Error error; + g_file_set_contents((cache_dir+local::FIRST_RUN_STAMP).c_str(), "", 0, &error); + + if (error) + { + LOG_ERROR(logger) << "Impossible to save the unity stamp file: " << error; + } + } + else + { + LOG_ERROR(logger) << "Impossible to create unity cache folder!"; + } + } + return false; + }); +} + /* Window init */ namespace @@ -3782,6 +3915,7 @@ UnityWindow::UnityWindow(CompWindow* window) , gWindow(GLWindow::get(window)) , close_icon_state_(decoration::WidgetState::NORMAL) , deco_win_(uScreen->deco_manager_->HandleWindow(window)) + , need_fake_deco_redraw_(false) , is_nux_window_(isNuxWindow(window)) { WindowInterface::setHandler(window); @@ -3955,14 +4089,11 @@ void UnityWindow::paintFakeDecoration(nux::Geometry const& geo, GLWindowPaintAtt { mask |= PAINT_WINDOW_BLEND_MASK; + if (!decoration_tex_ && compiz_utils::IsWindowFullyDecorable(window)) + BuildDecorationTexture(); + if (!highlighted) { - if (!compiz_utils::IsWindowFullyDecorable(window)) - return; - - if (!decoration_tex_) - BuildDecorationTexture(); - if (decoration_tex_) DrawTexture(*decoration_tex_, attrib, transform, mask, geo.x, geo.y, scale); @@ -4005,7 +4136,14 @@ void UnityWindow::paintFakeDecoration(nux::Geometry const& geo, GLWindowPaintAtt int text_x = padding.left + (close_texture ? close_texture->width() : 0) / dpi_scale; RenderTitle(context, text_x, padding.top, (width - padding.right) / dpi_scale, height / dpi_scale, scale); decoration_selected_tex_ = context; + decoration_title_ = deco_win_->title(); uScreen->damageRegion(CompRegionFromNuxGeo(geo)); + need_fake_deco_redraw_ = true; + + if (decoration_tex_) + DrawTexture(*decoration_tex_, attrib, transform, mask, geo.x, geo.y, scale); + + return; // Let's draw this at next repaint cycle } else { @@ -4013,6 +4151,10 @@ void UnityWindow::paintFakeDecoration(nux::Geometry const& geo, GLWindowPaintAtt redraw_decoration = false; } } + else + { + need_fake_deco_redraw_ = false; + } if (decoration_selected_tex_) DrawTexture(*decoration_selected_tex_, attrib, transform, mask, geo.x, geo.y); @@ -4049,7 +4191,7 @@ void UnityWindow::scalePaintDecoration(GLWindowPaintAttrib const& attrib, auto state = uScreen->sScreen->getState(); - if (state != ScaleScreen::Wait && state != ScaleScreen::Out) + if (state != ScaleScreen::Wait && state != ScaleScreen::Out && !need_fake_deco_redraw_) return; nux::Geometry const& scale_geo = GetScaledGeometry(); diff --git a/plugins/unityshell/src/unityshell.h b/plugins/unityshell/src/unityshell.h index a57ce4568..a9bf144d7 100644 --- a/plugins/unityshell/src/unityshell.h +++ b/plugins/unityshell/src/unityshell.h @@ -109,6 +109,7 @@ class UnityScreen : public ScreenInterface, public CompositeScreenInterface, public GLScreenInterface, + public ScaleScreenInterface, public BaseSwitchScreen, public PluginClassHandler <UnityScreen, CompScreen>, public CompAction::Container, @@ -172,6 +173,9 @@ public: void enterShowDesktopMode (); void leaveShowDesktopMode (CompWindow *w); + /* window scaling */ + bool layoutSlotsAndAssignWindows(); + bool showMenuBarInitiate(CompAction* action, CompAction::State state, CompOption::Vector& options); bool showMenuBarTerminate(CompAction* action, CompAction::State state, CompOption::Vector& options); bool showLauncherKeyInitiate(CompAction* action, CompAction::State state, CompOption::Vector& options); @@ -274,8 +278,7 @@ private: void OnLauncherStartKeyNav(GVariant* data); void OnLauncherEndKeyNav(GVariant* data); - - void OnSwitcherEnd(GVariant* data); + void OnSwitcherDetailChanged(bool detail); void OnInitiateSpread(); void OnTerminateSpread(); @@ -306,6 +309,8 @@ private: void DamageBlurUpdateRegion(nux::Geometry const&); + void ShowFirstRunHints(); + std::unique_ptr<na::TickSource> tick_source_; std::unique_ptr<na::AnimationController> animation_controller_; @@ -552,6 +557,7 @@ private: nux::Geometry close_button_geo_; std::shared_ptr<decoration::Window> deco_win_; bool middle_clicked_; + bool need_fake_deco_redraw_; bool is_nux_window_; glib::Source::UniquePtr focus_desktop_timeout_; diff --git a/plugins/unityshell/unityshell.xml.in b/plugins/unityshell/unityshell.xml.in index cefb87537..86ab214b5 100644 --- a/plugins/unityshell/unityshell.xml.in +++ b/plugins/unityshell/unityshell.xml.in @@ -23,7 +23,6 @@ <plugin>cube</plugin> <plugin>rotate</plugin> <plugin>cubeaddon</plugin> - <plugin>gnomecompat</plugin> <plugin>vpswitch</plugin> <plugin>fade</plugin> <plugin>staticswitcher</plugin> @@ -44,6 +43,7 @@ <conflict> <plugin>decor</plugin> <plugin>scalefilter</plugin> + <plugin>gnomecompat</plugin> </conflict> </deps> diff --git a/po/POTFILES.in b/po/POTFILES.in index df28a9aa7..486182514 100644 --- a/po/POTFILES.in +++ b/po/POTFILES.in @@ -31,6 +31,7 @@ plugins/unity-mt-grab-handles/unitymtgrabhandles.xml.in plugins/unitydialog/unitydialog.xml.in plugins/unityshell/src/unity-dash-view-accessible.cpp plugins/unityshell/src/unity-launcher-accessible.cpp +plugins/unityshell/src/unity-launcher-icon-accessible.cpp plugins/unityshell/src/unity-quicklist-menu-accessible.cpp plugins/unityshell/src/unity-search-bar-accessible.cpp plugins/unityshell/src/unity-switcher-accessible.cpp diff --git a/services/panel-service.c b/services/panel-service.c index 17789027b..e75fe4d96 100644 --- a/services/panel-service.c +++ b/services/panel-service.c @@ -277,7 +277,7 @@ panel_service_class_init (PanelServiceClass *klass) g_type_class_add_private (obj_class, sizeof (PanelServicePrivate)); } -static IndicatorObjectEntry * +IndicatorObjectEntry * get_entry_at (PanelService *self, gint x, gint y) { GHashTableIter panel_iter, entries_iter; @@ -305,6 +305,37 @@ get_entry_at (PanelService *self, gint x, gint y) return NULL; } +static IndicatorObjectEntry * +get_entry_at_panel (PanelService *self, const gchar *panel, gint x, gint y) +{ + GHashTable *entry2geometry_hash; + GHashTableIter entries_iter; + gpointer key, value; + + if (!panel) + return NULL; + + entry2geometry_hash = g_hash_table_lookup (self->priv->panel2entries_hash, panel); + + if (!entry2geometry_hash) + return NULL; + + g_hash_table_iter_init (&entries_iter, entry2geometry_hash); + while (g_hash_table_iter_next (&entries_iter, &key, &value)) + { + IndicatorObjectEntry *entry = key; + GdkRectangle *geo = value; + + if (x >= geo->x && x <= (geo->x + geo->width) && + y >= geo->y && y <= (geo->y + geo->height)) + { + return entry; + } + } + + return NULL; +} + static const gchar* get_panel_at (PanelService *self, gint x, gint y) { @@ -493,7 +524,7 @@ event_filter (GdkXEvent *ev, GdkEvent *gev, PanelService *self) case XI_ButtonPress: { - priv->pressed_entry = get_entry_at (self, event->root_x, event->root_y); + priv->pressed_entry = get_entry_at_panel (self, priv->last_panel, event->root_x, event->root_y); priv->use_event = (priv->pressed_entry == NULL); if (priv->pressed_entry) @@ -504,9 +535,9 @@ event_filter (GdkXEvent *ev, GdkEvent *gev, PanelService *self) case XI_ButtonRelease: { - IndicatorObjectEntry *entry; + IndicatorObjectEntry *entry = NULL; gboolean event_is_a_click = FALSE; - entry = get_entry_at (self, event->root_x, event->root_y); + entry = get_entry_at_panel (self, priv->last_panel, event->root_x, event->root_y); if (event->detail == 1 || event->detail == 3) { @@ -1414,6 +1445,9 @@ sort_indicators (PanelService *self) static gchar * gtk_image_to_data (GtkImage *image, guint32 *storage_type) { + if (!GTK_IS_IMAGE (image)) + return NULL; + *storage_type = gtk_image_get_storage_type (image); gchar *ret = NULL; @@ -1453,8 +1487,6 @@ gtk_image_to_data (GtkImage *image, guint32 *storage_type) g_warning ("Unable to convert pixbuf to png data: '%s'", error ? error->message : "unknown"); if (error) g_error_free (error); - - ret = g_strdup (""); } break; @@ -1480,12 +1512,10 @@ gtk_image_to_data (GtkImage *image, guint32 *storage_type) } case GTK_IMAGE_EMPTY: { - ret = g_strdup (""); break; } default: { - ret = g_strdup (""); g_warning ("Unable to support GtkImageType: %u", *storage_type); } } @@ -1513,7 +1543,7 @@ indicator_entry_to_variant (IndicatorObjectEntry *entry, is_label ? gtk_widget_get_sensitive (GTK_WIDGET (entry->label)) : FALSE, is_label ? gtk_widget_get_visible (GTK_WIDGET (entry->label)) : FALSE, is_image ? image_type : 0, - is_image ? image_data : "", + image_data ? image_data : "", is_image ? gtk_widget_get_sensitive (GTK_WIDGET (entry->image)) : FALSE, is_image ? gtk_widget_get_visible (GTK_WIDGET (entry->image)) : FALSE, prio); @@ -1612,7 +1642,11 @@ positon_menu (GtkMenu *menu, PanelService *self = PANEL_SERVICE (user_data); PanelServicePrivate *priv = self->priv; - gint scale = get_monitor_scale_at (priv->last_x, priv->last_y); + GdkScreen *screen = gdk_screen_get_default (); + gint monitor = gdk_screen_get_monitor_at_point (screen, priv->last_x, priv->last_y); + gtk_menu_set_monitor (menu, monitor); + + gint scale = gdk_screen_get_monitor_scale_factor (screen, monitor); *x = priv->last_x / scale; *y = priv->last_y / scale; *push = TRUE; diff --git a/shortcuts/ShortcutController.cpp b/shortcuts/ShortcutController.cpp index da796d9ca..5f56bf99d 100644 --- a/shortcuts/ShortcutController.cpp +++ b/shortcuts/ShortcutController.cpp @@ -37,7 +37,8 @@ const unsigned int FADE_DURATION = 100; Controller::Controller(BaseWindowRaiser::Ptr const& base_window_raiser, AbstractModeller::Ptr const& modeller) - : modeller_(modeller) + : first_run(false) + , modeller_(modeller) , base_window_raiser_(base_window_raiser) , visible_(false) , enabled_(true) @@ -155,6 +156,7 @@ void Controller::ConstructView() AddChild(view_.GetPointer()); view_->SetModel(modeller_->GetCurrentModel()); view_->background_color = WindowManager::Default().average_color(); + view_->closable = first_run(); if (!view_window_) { @@ -197,6 +199,8 @@ void Controller::Hide() if (view_window_ && view_window_->GetOpacity() > 0.0f) { view_->live_background = false; + view_->closable = false; + first_run = false; animation::StartOrReverse(fade_animator_, animation::Direction::BACKWARD); } } diff --git a/shortcuts/ShortcutController.h b/shortcuts/ShortcutController.h index c4a89c6f9..956fcb32b 100644 --- a/shortcuts/ShortcutController.h +++ b/shortcuts/ShortcutController.h @@ -47,6 +47,8 @@ public: Controller(BaseWindowRaiser::Ptr const& raiser, AbstractModeller::Ptr const& modeller); virtual ~Controller(); + nux::Property<bool> first_run; + bool Show(); void Hide(); diff --git a/tests/MockSwitcherController.h b/tests/MockSwitcherController.h index 4425fc486..a4afeb9be 100644 --- a/tests/MockSwitcherController.h +++ b/tests/MockSwitcherController.h @@ -49,11 +49,9 @@ public: MOCK_CONST_METHOD1(CanShowSwitcher, bool(const std::vector<launcher::AbstractLauncherIcon::Ptr> &)); MOCK_METHOD0(NextDetail, void()); MOCK_METHOD0(PrevDetail, void()); - MOCK_METHOD2(SetDetail, void(bool, unsigned int)); MOCK_METHOD0(SelectFirstItem, void()); MOCK_METHOD2(SetWorkspace, void(nux::Geometry, int)); - MOCK_METHOD0(ExternalRenderTargets, unity::ui::LayoutWindow::Vector ()); - MOCK_CONST_METHOD0(GetSwitcherInputWindowId, guint()); + MOCK_CONST_METHOD0(ExternalRenderTargets, unity::ui::LayoutWindow::Vector const&()); MOCK_CONST_METHOD0(IsShowDesktopDisabled, bool()); MOCK_METHOD1(SetShowDesktopDisabled, void(bool)); MOCK_CONST_METHOD0(StartIndex, int()); diff --git a/tests/autopilot/unity/tests/launcher/test_icon_behavior.py b/tests/autopilot/unity/tests/launcher/test_icon_behavior.py index e469be7fa..8d743575e 100644 --- a/tests/autopilot/unity/tests/launcher/test_icon_behavior.py +++ b/tests/autopilot/unity/tests/launcher/test_icon_behavior.py @@ -241,21 +241,6 @@ class LauncherIconsTests(LauncherTestCase): self.assertThat(self.unity.dash.visible, Eventually(Equals(True))) self.assertThat(self.unity.window_manager.scale_active, Eventually(Equals(False))) - def test_icon_shows_on_quick_application_reopen(self): - """Icons must stay on launcher when an application is quickly closed/reopened.""" - calc = self.process_manager.start_app("Calculator") - desktop_file = calc.desktop_file - calc_icon = self.unity.launcher.model.get_icon(desktop_id=desktop_file) - self.assertThat(calc_icon.visible, Eventually(Equals(True))) - - self.process_manager.close_all_app("Calculator") - calc = self.process_manager.start_app("Calculator") - sleep(2) - - calc_icon = self.unity.launcher.model.get_icon(desktop_id=desktop_file) - self.assertThat(calc_icon, NotEquals(None)) - self.assertThat(calc_icon.visible, Eventually(Equals(True))) - def test_right_click_on_icon_ends_expo(self): """Right click on a launcher icon in expo mode must end the expo and show the quicklist. diff --git a/tests/test_application_launcher_icon.cpp b/tests/test_application_launcher_icon.cpp index 1c7735783..3fc21543a 100644 --- a/tests/test_application_launcher_icon.cpp +++ b/tests/test_application_launcher_icon.cpp @@ -668,8 +668,14 @@ TEST_F(TestApplicationLauncherIcon, PerformScrollSwitchDirection) mock_icon->PerformScroll(AbstractLauncherIcon::ScrollDirection::DOWN, 200); EXPECT_THAT(WM->GetWindowsInStackingOrder(), testing::ElementsAre(7, 6, 5, 4, 3, 1, 2)); - mock_icon->PerformScroll(AbstractLauncherIcon::ScrollDirection::UP, 400); - EXPECT_THAT(WM->GetWindowsInStackingOrder(), testing::ElementsAre(7, 6, 4, 3, 1, 2, 5)); + mock_icon->PerformScroll(AbstractLauncherIcon::ScrollDirection::DOWN, 400); + EXPECT_THAT(WM->GetWindowsInStackingOrder(), testing::ElementsAre(7, 6, 5, 4, 2, 1, 3)); + + mock_icon->PerformScroll(AbstractLauncherIcon::ScrollDirection::UP, 600); + EXPECT_THAT(WM->GetWindowsInStackingOrder(), testing::ElementsAre(7, 6, 5, 4, 3, 1, 2)); + + mock_icon->PerformScroll(AbstractLauncherIcon::ScrollDirection::UP, 800); + EXPECT_THAT(WM->GetWindowsInStackingOrder(), testing::ElementsAre(7, 6, 5, 4, 3, 2, 1)); } TEST_F(TestApplicationLauncherIcon, PerformScrollNoWindows) diff --git a/tests/test_launcher_controller.cpp b/tests/test_launcher_controller.cpp index eb383520e..ebae3101f 100644 --- a/tests/test_launcher_controller.cpp +++ b/tests/test_launcher_controller.cpp @@ -41,7 +41,8 @@ #include "test_mock_devices.h" #include "test_mock_filemanager.h" #include "mock-application.h" - +#include "BamfApplicationManager.h" +#include "bamf-mock-application.h" using namespace testmocks; using namespace unity::launcher; @@ -1954,4 +1955,34 @@ TEST_F(TestLauncherController, SetNonExistingLauncherIconAsFavorite) EXPECT_TRUE(favorite_store.IsFavorite(icon_uri)); } +TEST_F(TestLauncherController, IconShowsOnQuickApplicationReopen) +{ + MockApplicationManager mock_manager; + unity::glib::Object<BamfMockApplication> bamf_mock_application(bamf_mock_application_new()); + ApplicationPtr app(new unity::bamf::Application(mock_manager, unity::glib::object_cast<BamfApplication>(bamf_mock_application))); + + MockApplicationLauncherIcon::Ptr our_icon; + + mock_manager.Default().application_started.emit(app); + + app->title.changed.emit("Hello"); + auto app_icons = lc.Impl()->model_->GetSublist<ApplicationLauncherIcon>(); + + for (auto const& icon : app_icons) + { + if (icon->tooltip_text() == "Hello") + { + our_icon = icon; + break; + } + } + ASSERT_TRUE(our_icon); + EXPECT_FALSE(our_icon->removed); + + app->closed.emit(); + app->running.changed(true); + Utils::WaitForTimeout(2); + + EXPECT_FALSE(our_icon->removed); +} } diff --git a/tests/test_layout_system.cpp b/tests/test_layout_system.cpp index 82a68a708..3fd9d1cb9 100644 --- a/tests/test_layout_system.cpp +++ b/tests/test_layout_system.cpp @@ -57,6 +57,7 @@ TEST_F(TestLayoutWindow, InitializationNormalWindow) EXPECT_EQ(lwin.geo, fake_window->geo); EXPECT_EQ(lwin.decoration_height, 0); EXPECT_EQ(lwin.selected, false); + EXPECT_FLOAT_EQ(lwin.scale, 1.0f); EXPECT_EQ(lwin.aspect_ratio, fake_window->geo().width / static_cast<float>(fake_window->geo().height)); } diff --git a/tests/test_shortcut_controller.cpp b/tests/test_shortcut_controller.cpp index 4de24b439..bdb612d21 100644 --- a/tests/test_shortcut_controller.cpp +++ b/tests/test_shortcut_controller.cpp @@ -68,6 +68,7 @@ class TestShortcutController : public Test MOCK_METHOD1(SetOpacity, void(double)); using Controller::GetOffsetPerMonitor; using Controller::ConstructView; + using Controller::OnShowTimer; using Controller::view_; void RealSetOpacity(double value) @@ -188,5 +189,37 @@ TEST_F(TestShortcutController, DisconnectWMSignalsOnDestruction) color_property.changed.emit(nux::color::RandomColor()); } +TEST_F(TestShortcutController, FirstRunFalse) +{ + ASSERT_FALSE(controller_.first_run()); + + controller_.ConstructView(); + EXPECT_FALSE(controller_.view_->closable()); +} + +TEST_F(TestShortcutController, FirstRunTrue) +{ + ASSERT_FALSE(controller_.first_run()); + + controller_.first_run = true; + controller_.ConstructView(); + EXPECT_TRUE(controller_.view_->closable()); +} + +TEST_F(TestShortcutController, UnsetFirstRunOnHide) +{ + controller_.first_run = true; + controller_.ConstructView(); + + ASSERT_TRUE(controller_.view_->closable()); + controller_.Show(); + controller_.OnShowTimer(); + tick_source_.tick(100 * 1000); + controller_.Hide(); + + EXPECT_FALSE(controller_.first_run()); + EXPECT_FALSE(controller_.view_->closable()); +} + } } diff --git a/tests/test_switcher_controller.cpp b/tests/test_switcher_controller.cpp index 5029dbe6f..87e29fb37 100644 --- a/tests/test_switcher_controller.cpp +++ b/tests/test_switcher_controller.cpp @@ -83,27 +83,27 @@ TEST_F(TestSwitcherController, StartDetailMode) { controller_->Show(ShowMode::ALL, SortMode::LAUNCHER_ORDER, icons_); controller_->InitiateDetail(); - EXPECT_TRUE(controller_->IsDetailViewShown()); + EXPECT_TRUE(controller_->detail()); auto const& view = controller_->GetView(); view->switcher_stop_detail.emit(); - EXPECT_FALSE(controller_->IsDetailViewShown()); + EXPECT_FALSE(controller_->detail()); view->switcher_start_detail.emit(); - EXPECT_TRUE(controller_->IsDetailViewShown()); + EXPECT_TRUE(controller_->detail()); } TEST_F(TestSwitcherController, StopDetailMode) { controller_->Show(ShowMode::ALL, SortMode::LAUNCHER_ORDER, icons_); controller_->InitiateDetail(); - EXPECT_TRUE(controller_->IsDetailViewShown()); + EXPECT_TRUE(controller_->detail()); auto const& view = controller_->GetView(); view->switcher_stop_detail.emit(); - EXPECT_FALSE(controller_->IsDetailViewShown()); + EXPECT_FALSE(controller_->detail()); } TEST_F(TestSwitcherController, StartDetailModeMovesNextRows) @@ -117,7 +117,7 @@ TEST_F(TestSwitcherController, StartDetailModeMovesNextRows) model->SetRowSizes({2,2}); view->switcher_start_detail.emit(); - EXPECT_TRUE(controller_->IsDetailViewShown()); + EXPECT_TRUE(controller_->detail()); view->switcher_start_detail.emit(); @@ -137,7 +137,7 @@ TEST_F(TestSwitcherController, StopDetailModeMovesPrevRows) auto const& view = controller_->GetView(); view->switcher_start_detail.emit(); - EXPECT_TRUE(controller_->IsDetailViewShown()); + EXPECT_TRUE(controller_->detail()); auto model = view->GetModel(); model->SetRowSizes({2,2}); @@ -153,7 +153,7 @@ TEST_F(TestSwitcherController, StopDetailModeMovesPrevRows) // Now we are in index 0, stoping detail mode must exit detail mode view->switcher_stop_detail.emit(); - EXPECT_FALSE(controller_->IsDetailViewShown()); + EXPECT_FALSE(controller_->detail()); } TEST_F(TestSwitcherController, ShowSwitcher) diff --git a/tests/test_switcher_controller_slow.cpp b/tests/test_switcher_controller_slow.cpp index 1b1e8b113..58deb59c9 100644 --- a/tests/test_switcher_controller_slow.cpp +++ b/tests/test_switcher_controller_slow.cpp @@ -107,8 +107,8 @@ TEST_F(TestSwitcherController, DetailTimeoutOnDetailActivate) EXPECT_EQ(controller_->GetCurrentSelection().window_, 0); // Manually open-close the detail mode before that the timeout has occurred - controller_->SetDetail(true); - controller_->SetDetail(false); + controller_->detail = true; + controller_->detail = false; Utils::WaitForTimeoutMSec(initial_details_timeout * 1.1); EXPECT_EQ(controller_->GetCurrentSelection().window_, 0); diff --git a/unity-shared/CompizUtils.cpp b/unity-shared/CompizUtils.cpp index 018ed2150..6084386f8 100644 --- a/unity-shared/CompizUtils.cpp +++ b/unity-shared/CompizUtils.cpp @@ -110,9 +110,13 @@ bool SimpleTextureQuad::SetY(int y) // PixmapTexture::PixmapTexture(int w, int h) - : pixmap_(XCreatePixmap(screen->dpy(), screen->root(), w, h, PIXMAP_DEPTH)) + : pixmap_(0) { - texture_ = GLTexture::bindPixmapToTexture(pixmap_, w, h, PIXMAP_DEPTH); + if (w > 0 && h > 0) + { + pixmap_ = XCreatePixmap(screen->dpy(), screen->root(), w, h, PIXMAP_DEPTH); + texture_ = GLTexture::bindPixmapToTexture(pixmap_, w, h, PIXMAP_DEPTH); + } } PixmapTexture::~PixmapTexture() diff --git a/unity-shared/IconTexture.cpp b/unity-shared/IconTexture.cpp index c906ac7a6..82530a765 100644 --- a/unity-shared/IconTexture.cpp +++ b/unity-shared/IconTexture.cpp @@ -110,6 +110,20 @@ void IconTexture::SetByFilePath(std::string const& file_path, unsigned int size) SetByIconName(file_path, size); } +void IconTexture::SetSize(unsigned size) +{ + _size = size; +} + +void IconTexture::ReLoadIcon() +{ + IconLoader::GetDefault().DisconnectHandle(_handle); + _handle = 0; + _loading = false; + + LoadIcon(); +} + void IconTexture::LoadIcon() { LOG_DEBUG(logger) << "LoadIcon called (" << _icon_name << ") - loading: " << _loading; diff --git a/unity-shared/IconTexture.h b/unity-shared/IconTexture.h index 4bf27cdd0..473aed2aa 100644 --- a/unity-shared/IconTexture.h +++ b/unity-shared/IconTexture.h @@ -52,7 +52,10 @@ public: void SetByFilePath(std::string const& file_path, unsigned int size); void GetTextureSize(int* width, int* height); + void SetSize(unsigned size); + void LoadIcon(); + void ReLoadIcon(); void SetOpacity(float opacity); diff --git a/unity-shared/LayoutSystem.cpp b/unity-shared/LayoutSystem.cpp index c3c3f5599..f2ea8b87a 100644 --- a/unity-shared/LayoutSystem.cpp +++ b/unity-shared/LayoutSystem.cpp @@ -125,12 +125,12 @@ nux::Geometry LayoutSystem::LayoutRow(LayoutWindow::Vector const& row, nux::Geom for (LayoutWindow::Ptr const& window : row) { // we dont allow scaling up - float final_scalar = std::min(1.0f, (unpadded_bounds.height / (float)window->geo.height) * global_scalar); + window->scale = std::min(1.0f, (unpadded_bounds.height / (float)window->geo.height) * global_scalar); window->result.x = x; window->result.y = y; - window->result.width = window->geo.width * final_scalar; - window->result.height = window->geo.height * final_scalar; + window->result.width = window->geo.width * window->scale; + window->result.height = window->geo.height * window->scale; x += window->result.width; } @@ -275,6 +275,7 @@ LayoutWindow::LayoutWindow(Window xid) , decoration_height(0) , selected(false) , aspect_ratio(geo.width / static_cast<float>(geo.height)) + , scale(1.0f) , alpha(0.0f) { auto& wm = WindowManager::Default(); diff --git a/unity-shared/LayoutSystem.h b/unity-shared/LayoutSystem.h index 4fd190b40..6241f727c 100644 --- a/unity-shared/LayoutSystem.h +++ b/unity-shared/LayoutSystem.h @@ -46,6 +46,7 @@ public: bool selected; float aspect_ratio; + float scale; float alpha; protected: diff --git a/unity-shared/PluginAdapter.cpp b/unity-shared/PluginAdapter.cpp index c2ea69dd2..5db3f5ecb 100644 --- a/unity-shared/PluginAdapter.cpp +++ b/unity-shared/PluginAdapter.cpp @@ -699,21 +699,14 @@ void PluginAdapter::RestoreAt(Window window_id, int x, int y) if (window && (window->state() & MAXIMIZE_STATE)) { nux::Geometry new_geo(GetWindowSavedGeometry(window_id)); - decoration::Border border; - double scale = 1.0f; - - if (compiz_utils::IsWindowFullyDecorable(window)) - { - auto& settings = Settings::Instance(); - border = decoration::Style::Get()->Border(); - scale = settings.em(MonitorGeometryIn(new_geo))->DPIScale(); - } + window->maximize(0); + auto const& border = window->border(); new_geo.x = x; - new_geo.y = y; - new_geo.width -= (border.left - border.right) * scale; - new_geo.height -= (border.top - border.bottom) * scale; - window->maximize(0); + new_geo.y = y + border.top; + new_geo.width -= (border.left + border.right); + new_geo.height -= (border.top + border.bottom); + MoveResizeWindow(window_id, new_geo); } } diff --git a/unity-shared/SearchBar.cpp b/unity-shared/SearchBar.cpp index 02ec0c3a0..5c2e87a1f 100644 --- a/unity-shared/SearchBar.cpp +++ b/unity-shared/SearchBar.cpp @@ -1,6 +1,6 @@ // -*- Mode: C++; indent-tabs-mode: nil; tab-width: 2 -*- /* - * Copyright (C) 2010-2011 Canonical Ltd + * Copyright (C) 2010-2014 Canonical Ltd * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License version 3 as @@ -30,19 +30,36 @@ #include "CairoTexture.h" #include "DashStyle.h" #include "GraphicsUtils.h" +#include "RawPixel.h" +#include "UnitySettings.h" + +namespace unity +{ namespace { +const double DEFAULT_SCALE = 1.0; const float DEFAULT_ICON_OPACITY = 1.0f; const int DEFAULT_LIVE_SEARCH_TIMEOUT = 40; const int SPINNER_TIMEOUT = 100; -const int SPACE_BETWEEN_SPINNER_AND_TEXT = 5; -const int SPACE_BETWEEN_ENTRY_AND_HIGHLIGHT = 10; -const int LEFT_INTERNAL_PADDING = 4; -const int SEARCH_ENTRY_RIGHT_BORDER = 10; +const RawPixel SPACE_BETWEEN_SPINNER_AND_TEXT = 5_em; +const RawPixel SPACE_BETWEEN_ENTRY_AND_HIGHLIGHT = 10_em; +const RawPixel LEFT_INTERNAL_PADDING = 4_em; +const RawPixel SEARCH_ENTRY_RIGHT_BORDER = 10_em; +const RawPixel LEFT_PADDING = 0_em; +const RawPixel RIGHT_PADDING = 10_em; + +const RawPixel HIGHLIGHT_HEIGHT = 24_em; + +const RawPixel ARROW_MIN_WIDTH = 2_em; +const RawPixel ARROW_MAX_WIDTH = 2_em; -const int HIGHLIGHT_HEIGHT = 24; +const RawPixel TOP_ARROW_MIN_HEIGHT = 12_em; +const RawPixel TOP_ARROW_MAX_HEIGHT = 12_em; + +const RawPixel BOT_ARROW_MIN_HEIGHT = 8_em; +const RawPixel BOT_ARROW_MAX_HEIGHT = 8_em; // Fonts const std::string HINT_LABEL_FONT_SIZE = "20px"; @@ -50,7 +67,7 @@ const std::string HINT_LABEL_FONT_STYLE = "Italic"; const std::string HINT_LABEL_DEFAULT_FONT = "Ubuntu " + HINT_LABEL_FONT_STYLE + " " + HINT_LABEL_FONT_SIZE; const std::string PANGO_ENTRY_DEFAULT_FONT_FAMILY = "Ubuntu"; -const int PANGO_ENTRY_FONT_SIZE = 22; +const RawPixel PANGO_ENTRY_FONT_SIZE = 22_em; const std::string SHOW_FILTERS_LABEL_FONT_SIZE = "13"; const std::string SHOW_FILTERS_LABEL_FONT_STYLE = ""; @@ -58,6 +75,8 @@ const std::string SHOW_FILTERS_LABEL_DEFAULT_FONT = "Ubuntu " + SHOW_FILTERS_LAB } +} + DECLARE_LOGGER(logger, "unity.dash.searchbar"); namespace { @@ -118,26 +137,21 @@ SearchBar::SearchBar(bool show_filter_hint, NUX_FILE_LINE_DECL) , show_filters_(nullptr) , last_width_(-1) , last_height_(-1) + , scale_(DEFAULT_SCALE) { dash::Style& style = dash::Style::Instance(); - nux::BaseTexture* icon = style.GetSearchMagnifyIcon(); bg_layer_.reset(new nux::ColorLayer(nux::Color(0xff595853), true)); layout_ = new nux::HLayout(NUX_TRACKER_LOCATION); - layout_->SetLeftAndRightPadding(LEFT_INTERNAL_PADDING, SEARCH_ENTRY_RIGHT_BORDER); - layout_->SetSpaceBetweenChildren(SPACE_BETWEEN_ENTRY_AND_HIGHLIGHT); SetLayout(layout_); entry_layout_ = new nux::HLayout(NUX_TRACKER_LOCATION); - entry_layout_->SetLeftAndRightPadding(0, 10); layout_->AddLayout(entry_layout_); spinner_ = new SearchBarSpinner(); - spinner_->SetMinMaxSize(icon->GetWidth(), icon->GetHeight()); spinner_->mouse_click.connect(sigc::mem_fun(this, &SearchBar::OnClearClicked)); entry_layout_->AddView(spinner_, 0, nux::MINOR_POSITION_CENTER, nux::MINOR_SIZE_FULL); - entry_layout_->SetSpaceBetweenChildren(SPACE_BETWEEN_SPINNER_AND_TEXT); nux::HLayout* hint_layout = new nux::HLayout(NUX_TRACKER_LOCATION); @@ -148,7 +162,6 @@ SearchBar::SearchBar(bool show_filter_hint, NUX_FILE_LINE_DECL) pango_entry_ = new IMTextEntry(); pango_entry_->SetFontFamily(PANGO_ENTRY_DEFAULT_FONT_FAMILY.c_str()); - pango_entry_->SetFontSize(PANGO_ENTRY_FONT_SIZE); pango_entry_->text_changed.connect(sigc::mem_fun(this, &SearchBar::OnSearchChanged)); pango_entry_->activated.connect([this]() { activated.emit(); }); pango_entry_->cursor_moved.connect([this](int i) { QueueDraw(); }); @@ -190,13 +203,22 @@ SearchBar::SearchBar(bool show_filter_hint, NUX_FILE_LINE_DECL) filter_layout_ = new nux::HLayout(); filter_layout_->SetHorizontalInternalMargin(8); - filter_layout_->SetLeftAndRightPadding(style.GetFilterResultsHighlightLeftPadding(), style.GetFilterResultsHighlightRightPadding()); + filter_layout_->SetLeftAndRightPadding(style.GetFilterResultsHighlightLeftPadding(), + style.GetFilterResultsHighlightRightPadding()); filter_layout_->SetContentDistribution(nux::MAJOR_POSITION_END); filter_layout_->AddView(show_filters_, 0, nux::MINOR_POSITION_CENTER); arrow_layout_ = new nux::VLayout(); - arrow_top_space_ = new nux::SpaceLayout(2, 2, 12, 12); - arrow_bottom_space_ = new nux::SpaceLayout(2, 2, 8, 8); + arrow_top_space_ = new nux::SpaceLayout(ARROW_MIN_WIDTH.CP(scale_), + ARROW_MAX_WIDTH.CP(scale_), + TOP_ARROW_MIN_HEIGHT.CP(scale_), + TOP_ARROW_MAX_HEIGHT.CP(scale_)); + + arrow_bottom_space_ = new nux::SpaceLayout(ARROW_MIN_WIDTH.CP(scale_), + ARROW_MAX_WIDTH.CP(scale_), + BOT_ARROW_MIN_HEIGHT.CP(scale_), + BOT_ARROW_MAX_HEIGHT.CP(scale_)); + arrow_layout_->AddView(arrow_top_space_, 0, nux::MINOR_POSITION_CENTER); arrow_layout_->AddView(expand_icon_, 0, nux::MINOR_POSITION_CENTER); arrow_layout_->AddView(arrow_bottom_space_, 0, nux::MINOR_POSITION_CENTER); @@ -259,6 +281,64 @@ SearchBar::SearchBar(bool show_filter_hint, NUX_FILE_LINE_DECL) expand_icon_->SetVisible(can_refine); } }); + + UpdateSearchBarSize(); +} + +void SearchBar::UpdateSearchBarSize() +{ + dash::Style& style = dash::Style::Instance(); + nux::BaseTexture* icon = style.GetSearchMagnifyIcon(); + RawPixel const icon_width = icon->GetWidth(); + RawPixel const icon_height = icon->GetHeight(); + + layout_->SetLeftAndRightPadding(LEFT_INTERNAL_PADDING.CP(scale_), + SEARCH_ENTRY_RIGHT_BORDER.CP(scale_)); + layout_->SetSpaceBetweenChildren(SPACE_BETWEEN_ENTRY_AND_HIGHLIGHT.CP(scale_)); + + entry_layout_->SetLeftAndRightPadding(LEFT_PADDING.CP(scale_), + RIGHT_PADDING.CP(scale_)); + + spinner_->SetMinMaxSize(icon_width.CP(scale_), icon_height.CP(scale_)); + entry_layout_->SetSpaceBetweenChildren(SPACE_BETWEEN_SPINNER_AND_TEXT.CP(scale_)); + + pango_entry_->SetFontSize(PANGO_ENTRY_FONT_SIZE.CP(scale_)); + + if (show_filter_hint_) + { + arrow_top_space_->SetMinimumSize(ARROW_MIN_WIDTH.CP(scale_), + TOP_ARROW_MIN_HEIGHT.CP(scale_)); + arrow_top_space_->SetMaximumSize(ARROW_MAX_WIDTH.CP(scale_), + TOP_ARROW_MAX_HEIGHT.CP(scale_)); + + arrow_bottom_space_->SetMinimumSize(ARROW_MIN_WIDTH.CP(scale_), + BOT_ARROW_MIN_HEIGHT.CP(scale_)); + arrow_bottom_space_->SetMaximumSize(ARROW_MAX_WIDTH.CP(scale_), + BOT_ARROW_MAX_HEIGHT.CP(scale_)); + } + + // Based on the Font size, the MinHeight is changing in TextEntry. From there the + // layered_layout grows to match the MinHeight, but when the MinHeight is shurnk it + // is not changing (since the MaxHeight is int::MAX). Now we grab the MinHeight from + // PangoEntry, and set it for layered_layout. + int entry_min = pango_entry_->GetMinimumHeight(); + + pango_entry_->SetMaximumHeight(entry_min); + layered_layout_->SetMinimumHeight(entry_min); + layered_layout_->SetMaximumHeight(entry_min); +} + +void SearchBar::UpdateScale(double scale) +{ + if (scale_ != scale) + { + scale_ = scale; + + hint_->SetScale(scale_); + show_filters_->SetScale(scale_); + + UpdateSearchBarSize(); + } } void SearchBar::OnFontChanged(GtkSettings* settings, GParamSpec* pspec) @@ -370,8 +450,8 @@ void SearchBar::Draw(nux::GraphicsEngine& graphics_engine, bool force_draw) nux::Geometry geo(expander_view_->GetGeometry()); - geo.y -= (HIGHLIGHT_HEIGHT- geo.height) / 2; - geo.height = HIGHLIGHT_HEIGHT; + geo.y -= (HIGHLIGHT_HEIGHT.CP(scale_) - geo.height) / 2; + geo.height = HIGHLIGHT_HEIGHT.CP(scale_); if (!highlight_layer_) highlight_layer_.reset(style.FocusOverlay(geo.width, geo.height)); @@ -463,12 +543,12 @@ void SearchBar::SetSearchFinished() void SearchBar::UpdateBackground(bool force) { - int RADIUS = 5; + RawPixel const RADIUS = 5; nux::Geometry geo(GetGeometry()); geo.width = layered_layout_->GetAbsoluteX() + layered_layout_->GetAbsoluteWidth() - GetAbsoluteX() + - SEARCH_ENTRY_RIGHT_BORDER; + SEARCH_ENTRY_RIGHT_BORDER.CP(scale_); LOG_TRACE(logger) << "height: " << geo.height << " - " @@ -490,7 +570,7 @@ void SearchBar::UpdateBackground(bool force) cairo_graphics.DrawRoundedRectangle(cr, 1.0f, 0.5, 0.5, - RADIUS, + RADIUS.CP(scale_), last_width_ - 1, last_height_ - 1, false); diff --git a/unity-shared/SearchBar.h b/unity-shared/SearchBar.h index e4f1505fa..aea7013e5 100644 --- a/unity-shared/SearchBar.h +++ b/unity-shared/SearchBar.h @@ -1,6 +1,6 @@ // -*- Mode: C++; indent-tabs-mode: nil; tab-width: 2 -*- /* - * Copyright (C) 2010 Canonical Ltd + * Copyright (C) 2010-2014 Canonical Ltd * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License version 3 as @@ -54,6 +54,8 @@ public: void ForceLiveSearch(); void SetSearchFinished(); + void UpdateScale(double scale); + nux::TextEntry* text_entry() const; nux::View* show_filters() const; @@ -99,6 +101,7 @@ private: private: bool ShouldBeHighlighted(); + void UpdateSearchBarSize(); std::unique_ptr<nux::AbstractPaintLayer> bg_layer_; std::unique_ptr<nux::AbstractPaintLayer> highlight_layer_; @@ -118,6 +121,7 @@ private: int last_width_; int last_height_; + double scale_; glib::SignalManager sig_manager_; glib::Source::UniquePtr live_search_timeout_; |
