Add support for client side decorations
This implements client side window decorations of our windows. The title bar of our windows is now drawn by Android and we simply map out the title bar area hit test area to SDL to detect when the other wants to move the window or resize it.
This commit is contained in:
parent
f1480bfb91
commit
bdc2a24f88
6 changed files with 112 additions and 9 deletions
|
|
@ -126,6 +126,7 @@ set(SOURCES
|
|||
anbox/graphics/buffer_queue.cpp
|
||||
anbox/graphics/buffered_io_stream.cpp
|
||||
anbox/graphics/gl_renderer_server.cpp
|
||||
anbox/graphics/density.cpp
|
||||
anbox/graphics/density.h
|
||||
anbox/graphics/rect.cpp
|
||||
anbox/graphics/layer_composer.cpp
|
||||
|
|
|
|||
30
src/anbox/graphics/density.cpp
Normal file
30
src/anbox/graphics/density.cpp
Normal file
|
|
@ -0,0 +1,30 @@
|
|||
/*
|
||||
* Copyright (C) 2016 Simon Fels <morphis@gravedo.de>
|
||||
*
|
||||
* 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 published
|
||||
* by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranties of
|
||||
* MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR
|
||||
* PURPOSE. See the GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along
|
||||
* with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "anbox/graphics/density.h"
|
||||
|
||||
namespace anbox {
|
||||
namespace graphics {
|
||||
DensityType current_density() {
|
||||
return DensityType::medium;
|
||||
}
|
||||
|
||||
int dp_to_pixel(unsigned int dp) {
|
||||
return dp * static_cast<unsigned int>(current_density()) / static_cast<unsigned int>(DensityType::medium);
|
||||
}
|
||||
} // namespace graphics
|
||||
} // namespace anbox
|
||||
|
|
@ -35,6 +35,9 @@ enum class DensityType {
|
|||
xhigh = 360,
|
||||
xxhigh = 480,
|
||||
};
|
||||
|
||||
DensityType current_density();
|
||||
int dp_to_pixel(unsigned int dp);
|
||||
} // namespace graphics
|
||||
} // namespace anbox
|
||||
|
||||
|
|
|
|||
|
|
@ -16,8 +16,9 @@
|
|||
*/
|
||||
|
||||
#include "anbox/platform/sdl/window.h"
|
||||
#include "anbox/logger.h"
|
||||
#include "anbox/wm/window_state.h"
|
||||
#include "anbox/graphics/density.h"
|
||||
#include "anbox/logger.h"
|
||||
|
||||
#include <boost/throw_exception.hpp>
|
||||
|
||||
|
|
@ -25,6 +26,14 @@
|
|||
#include <mir_toolkit/mir_client_library.h>
|
||||
#endif
|
||||
|
||||
namespace {
|
||||
constexpr const int window_resize_border{30};
|
||||
constexpr const int top_drag_area{50};
|
||||
constexpr const int button_size{32};
|
||||
constexpr const int button_margin{5};
|
||||
constexpr const int button_padding{4};
|
||||
}
|
||||
|
||||
namespace anbox {
|
||||
namespace platform {
|
||||
namespace sdl {
|
||||
|
|
@ -43,15 +52,14 @@ Window::Window(const std::shared_ptr<Renderer> &renderer,
|
|||
observer_(observer),
|
||||
native_display_(0),
|
||||
native_window_(0) {
|
||||
|
||||
SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 2);
|
||||
SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 1);
|
||||
|
||||
// NOTE: We don't furce GL initialization of the window as this will
|
||||
// be take care of by the Renderer when we attach to it. On EGL
|
||||
// initializing GL here will cause a surface to be created and the
|
||||
// renderer will attempt to create one too which will not work as
|
||||
// only a single surface per EGLNativeWindowType is supported.
|
||||
std::uint32_t flags = 0;
|
||||
std::uint32_t flags = SDL_WINDOW_BORDERLESS;
|
||||
if (resizable)
|
||||
flags |= SDL_WINDOW_RESIZABLE;
|
||||
|
||||
|
|
@ -64,6 +72,9 @@ Window::Window(const std::shared_ptr<Renderer> &renderer,
|
|||
BOOST_THROW_EXCEPTION(std::runtime_error(message));
|
||||
}
|
||||
|
||||
if (SDL_SetWindowHitTest(window_, &Window::on_window_hit, this) < 0)
|
||||
BOOST_THROW_EXCEPTION(std::runtime_error("Failed to register for window hit test"));
|
||||
|
||||
SDL_SysWMinfo info;
|
||||
SDL_VERSION(&info.version);
|
||||
SDL_GetWindowWMInfo(window_, &info);
|
||||
|
|
@ -92,6 +103,58 @@ Window::~Window() {
|
|||
if (window_) SDL_DestroyWindow(window_);
|
||||
}
|
||||
|
||||
SDL_HitTestResult Window::on_window_hit(SDL_Window *window, const SDL_Point *pt, void *data) {
|
||||
auto platform_window = reinterpret_cast<Window*>(data);
|
||||
|
||||
int w = 0, h = 0;
|
||||
SDL_GetWindowSize(window, &w, &h);
|
||||
|
||||
const auto border_size = graphics::dp_to_pixel(window_resize_border);
|
||||
const auto top_drag_area_height = graphics::dp_to_pixel(top_drag_area);
|
||||
const auto button_area_width = graphics::dp_to_pixel(button_size + button_padding * 2 + button_margin * 2);
|
||||
|
||||
if (pt->y < top_drag_area_height) {
|
||||
if (pt->x > w - button_area_width && pt->x < w) {
|
||||
platform_window->close();
|
||||
return SDL_HITTEST_NORMAL;
|
||||
} else if (pt->x > w - button_area_width * 2 && pt->x < w - button_area_width) {
|
||||
platform_window->switch_window_state();
|
||||
return SDL_HITTEST_NORMAL;
|
||||
}
|
||||
return SDL_HITTEST_DRAGGABLE;
|
||||
} else if (pt->x < border_size && pt->y < border_size)
|
||||
return SDL_HITTEST_RESIZE_TOPLEFT;
|
||||
else if (pt->x > window_resize_border && pt->x < w - border_size && pt->y < border_size)
|
||||
return SDL_HITTEST_RESIZE_TOP;
|
||||
else if (pt->x > w - border_size && pt->y < border_size)
|
||||
return SDL_HITTEST_RESIZE_TOPRIGHT;
|
||||
else if (pt->x > w - border_size && pt->y > border_size && pt->y < h - border_size)
|
||||
return SDL_HITTEST_RESIZE_RIGHT;
|
||||
else if (pt->x > w - border_size && pt->y > h - border_size)
|
||||
return SDL_HITTEST_RESIZE_BOTTOMRIGHT;
|
||||
else if (pt->x < w - border_size && pt->x > border_size && pt->y > h - border_size)
|
||||
return SDL_HITTEST_RESIZE_BOTTOM;
|
||||
else if (pt->x < border_size && pt->y > h - border_size)
|
||||
return SDL_HITTEST_RESIZE_BOTTOMLEFT;
|
||||
else if (pt->x < border_size && pt->y < h - border_size && pt->y > border_size)
|
||||
return SDL_HITTEST_RESIZE_LEFT;
|
||||
|
||||
return SDL_HITTEST_NORMAL;
|
||||
}
|
||||
|
||||
void Window::close() {
|
||||
if (observer_)
|
||||
observer_->window_deleted(id_);
|
||||
}
|
||||
|
||||
void Window::switch_window_state() {
|
||||
const auto flags = SDL_GetWindowFlags(window_);
|
||||
if (flags & SDL_WINDOW_MAXIMIZED)
|
||||
SDL_RestoreWindow(window_);
|
||||
else
|
||||
SDL_MaximizeWindow(window_);
|
||||
}
|
||||
|
||||
void Window::process_event(const SDL_Event &event) {
|
||||
switch (event.window.event) {
|
||||
case SDL_WINDOWEVENT_FOCUS_GAINED:
|
||||
|
|
@ -114,7 +177,10 @@ void Window::process_event(const SDL_Event &event) {
|
|||
case SDL_WINDOWEVENT_HIDDEN:
|
||||
break;
|
||||
case SDL_WINDOWEVENT_CLOSE:
|
||||
if (observer_) observer_->window_deleted(id_);
|
||||
if (observer_)
|
||||
observer_->window_deleted(id_);
|
||||
|
||||
close();
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
|
|
|
|||
|
|
@ -62,6 +62,11 @@ class Window : public std::enable_shared_from_this<Window>, public wm::Window {
|
|||
std::uint32_t window_id() const;
|
||||
|
||||
private:
|
||||
static SDL_HitTestResult on_window_hit(SDL_Window *window, const SDL_Point *pt, void *data);
|
||||
|
||||
void close();
|
||||
void switch_window_state();
|
||||
|
||||
Id id_;
|
||||
std::shared_ptr<Observer> observer_;
|
||||
EGLNativeDisplayType native_display_;
|
||||
|
|
|
|||
|
|
@ -35,10 +35,8 @@ void BootPropertiesMessageProcessor::handle_command(
|
|||
void BootPropertiesMessageProcessor::list_properties() {
|
||||
std::vector<std::string> properties = {
|
||||
// TODO(morphis): Using HDPI here for now but should be adjusted to the
|
||||
// device
|
||||
// we're running on.
|
||||
utils::string_format("ro.sf.lcd_density=%d",
|
||||
static_cast<int>(graphics::DensityType::medium)),
|
||||
// device we're running on
|
||||
utils::string_format("ro.sf.lcd_density=%d", static_cast<int>(graphics::current_density())),
|
||||
};
|
||||
|
||||
for (const auto &prop : properties) {
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue