diff options
-rw-r--r-- | src/layers.cpp | 7 | ||||
-rw-r--r-- | src/layers.hpp | 2 | ||||
-rw-r--r-- | src/util.cpp | 53 | ||||
-rw-r--r-- | src/util.hpp | 54 | ||||
-rw-r--r-- | src/wayland_ivi_wm.hpp | 3 | ||||
-rw-r--r-- | src/window_manager.cpp | 30 | ||||
-rw-r--r-- | src/window_manager.hpp | 1 |
7 files changed, 141 insertions, 9 deletions
diff --git a/src/layers.cpp b/src/layers.cpp index f73daf2..bbe7c09 100644 --- a/src/layers.cpp +++ b/src/layers.cpp @@ -181,7 +181,7 @@ json layer_map::to_json() const return j; } -void layer_map::setupArea(int output_w, int output_h) +void layer_map::setupArea(double scaling) { compositor::rect rct; @@ -191,6 +191,11 @@ void layer_map::setupArea(int output_w, int output_h) for (auto &i : this->area2size) { + i.second.x = static_cast<int>(scaling * i.second.x + 0.5); + i.second.y = static_cast<int>(scaling * i.second.y + 0.5); + i.second.w = static_cast<int>(scaling * i.second.w + 0.5); + i.second.h = static_cast<int>(scaling * i.second.h + 0.5); + HMI_DEBUG("wm:lm", "area:%s size(after) : x:%d y:%d w:%d h:%d", i.first.c_str(), i.second.x, i.second.y, i.second.w, i.second.h); } diff --git a/src/layers.hpp b/src/layers.hpp index b6dd67f..f52886e 100644 --- a/src/layers.hpp +++ b/src/layers.hpp @@ -114,7 +114,7 @@ struct layer_map } json to_json() const; - void setupArea(int output_w, int output_h); + void setupArea(double scaling); compositor::rect getAreaSize(const std::string &area); int loadAreaDb(); diff --git a/src/util.cpp b/src/util.cpp index 19d590e..672b089 100644 --- a/src/util.cpp +++ b/src/util.cpp @@ -40,3 +40,56 @@ unique_fd::~unique_fd() close(this->fd); } } + +void rectangle::fit(unsigned long to_width, unsigned long to_height) +{ + // fit rect within (to_width x to_height) + + if (to_width <= width()) { + // scale to fit with + set_bottom(top() + (static_cast<long>(to_width) * height() / width()) - 1); + set_right(left() + to_width - 1); + } else { + // scale to fit height + set_right(left() + (static_cast<long>(to_height) * width () / height()) - 1); + set_bottom(top() + to_height - 1); + } +} + +void rectangle::center(unsigned long outer_w, unsigned long outer_h) +{ + long inner_w = width(); + long inner_h = height(); + + set_left((outer_w - inner_w) / 2); + set_right(left() + inner_w - 1); + set_top((outer_h - inner_h) / 2); + set_bottom(top() + inner_h - 1); +} + +void rectangle::set_aspect(double ratio) +{ + // aspect ratio is width:height (= width/height) + // e.g. Landscape of HD's ratio is 16:9 (= 1.777...) + // Portrait of HD's ratio is 9:16 (= 0.5625) + // + // width / height = ratio + // width * height = area + // + // width = sqrt(ratio * area) + // height = width / ratio + + long orig_w = width(); + long orig_h = height(); + + if (ratio >= 1) { + // width >= height + // try to keep width + set_right(left() + orig_w - 1); + set_bottom(top() + static_cast<long>(orig_w / ratio + 0.5) - 1); + } else { + set_bottom(top() + orig_h - 1); + set_right(left() + static_cast<long>(orig_h * ratio + 0.5) - 1); + } +} + diff --git a/src/util.hpp b/src/util.hpp index 78d2185..2f17845 100644 --- a/src/util.hpp +++ b/src/util.hpp @@ -109,4 +109,58 @@ struct unique_fd } }; +class rectangle +{ + public: + explicit rectangle(long wd, long ht) : _right(wd - 1), _bottom(ht - 1) {}; + + void set_left(long l) { + _left = l; + } + long left() const { return _left; }; + + void set_right(long r) { + _right = r; + } + long right() const { return _right; }; + + void set_top(long t) { + _top = t; + } + long top() const { return _top; }; + + void set_bottom(long b) { + _bottom = b; + } + long bottom() const { return _bottom; } + + long width() const { + if (is_valid()) + return 0; + else + return _right - _left + 1; + } + + long height() const { + if (is_valid()) + return 0; + else + return _bottom - _top + 1; + } + + void set_aspect(double ratio); + void fit(unsigned long to_width, unsigned long to_height); + void center(unsigned long outer_w, unsigned long outer_h); + + private: + bool is_valid() const { + return (_top > _bottom || _left > _right); + } + + long _left = 0; + long _top = 0; + long _right; + long _bottom; +}; + #endif // !WM_UTIL_HPP diff --git a/src/wayland_ivi_wm.hpp b/src/wayland_ivi_wm.hpp index 9d0c7a7..a430927 100644 --- a/src/wayland_ivi_wm.hpp +++ b/src/wayland_ivi_wm.hpp @@ -256,6 +256,9 @@ struct controller : public wayland_proxy<struct ivi_wm> size output_size; // Display size[pixel] size physical_size; // Display size[mm] + // Scale for conversion CSS PX -> DP(Device Pixel) + double scale; + wm::controller_hooks *chooks; struct wl::display *display; diff --git a/src/window_manager.cpp b/src/window_manager.cpp index 862341a..c44210f 100644 --- a/src/window_manager.cpp +++ b/src/window_manager.cpp @@ -50,6 +50,7 @@ const char kKeyWidthPixel[] = "width_pixel"; const char kKeyHeightPixel[] = "height_pixel"; const char kKeyWidthMm[] = "width_mm"; const char kKeyHeightMm[] = "height_mm"; +const char kKeyScale[] = "scale"; const char kKeyIds[] = "ids"; static sd_event_source *g_timer_ev_src = nullptr; @@ -460,10 +461,9 @@ void WindowManager::api_enddraw(char const *appid, char const *drawing_name) result<json_object *> WindowManager::api_get_display_info() { - // Check controller - if (!this->controller) + if (!this->display->ok()) { - return Err<json_object *>("ivi_controller global not available"); + return Err<json_object *>("Wayland compositor is not available"); } // Set display info @@ -475,6 +475,7 @@ result<json_object *> WindowManager::api_get_display_info() json_object_object_add(object, kKeyHeightPixel, json_object_new_int(o_size.h)); json_object_object_add(object, kKeyWidthMm, json_object_new_int(p_size.w)); json_object_object_add(object, kKeyHeightMm, json_object_new_int(p_size.h)); + json_object_object_add(object, kKeyScale, json_object_new_double(this->controller->scale)); return Ok<json_object *>(object); } @@ -665,6 +666,21 @@ int WindowManager::init_layers() c->physical_size = compositor::size{uint32_t(o->physical_width), uint32_t(o->physical_height)}; + + HMI_DEBUG("wm", "SCALING: screen (%dx%d), physical (%dx%d)", + o->width, o->height, o->physical_width, o->physical_height); + + this->layers.loadAreaDb(); + + const compositor::rect css_bg = this->layers.getAreaSize("fullscreen"); + rectangle dp_bg(o->width, o->height); + + dp_bg.set_aspect(static_cast<double>(css_bg.w) / css_bg.h); + dp_bg.fit(o->width, o->height); + dp_bg.center(o->width, o->height); + HMI_DEBUG("wm", "SCALING: CSS BG(%dx%d) -> DDP %dx%d,(%dx%d)", + css_bg.w, css_bg.h, dp_bg.left(), dp_bg.top(), dp_bg.width(), dp_bg.height()); + // Clear scene layers.clear(); @@ -674,9 +690,9 @@ int WindowManager::init_layers() // Quick and dirty setup of layers for (auto const &i : this->layers.mapping) { - c->layer_create(i.second.layer_id, o->width, o->height); + c->layer_create(i.second.layer_id, dp_bg.width(), dp_bg.height()); auto &l = layers[i.second.layer_id]; - l->set_destination_rectangle(0, 0, o->width, o->height); + l->set_destination_rectangle(dp_bg.left(), dp_bg.top(), dp_bg.width(), dp_bg.height()); l->set_visibility(1); HMI_DEBUG("wm", "Setting up layer %s (%d) for surface role match \"%s\"", i.second.name.c_str(), i.second.layer_id, i.second.role.c_str()); @@ -687,8 +703,8 @@ int WindowManager::init_layers() this->layout_commit(); - this->layers.loadAreaDb(); - this->layers.setupArea(o->width, o->height); + c->scale = static_cast<double>(dp_bg.height()) / css_bg.h; + this->layers.setupArea(c->scale); return 0; } diff --git a/src/window_manager.hpp b/src/window_manager.hpp index ebdf495..2358c5a 100644 --- a/src/window_manager.hpp +++ b/src/window_manager.hpp @@ -65,6 +65,7 @@ extern const char kKeyWidthPixel[]; extern const char kKeyHeightPixel[]; extern const char kKeyWidthMm[]; extern const char kKeyHeightMm[]; +extern const char kKeyScale[]; extern const char kKeyIds[]; struct id_allocator |