Squash commits for public release
This commit is contained in:
76
userland/servers/window_server/src/Target/Desktop/Window.cpp
Normal file
76
userland/servers/window_server/src/Target/Desktop/Window.cpp
Normal file
@@ -0,0 +1,76 @@
|
||||
#include "Window.h"
|
||||
#include "../../Managers/WindowManager.h"
|
||||
#include <utility>
|
||||
|
||||
namespace WinServer::Desktop {
|
||||
|
||||
Window::Window(int connection_id, int id, CreateWindowMessage& msg)
|
||||
: BaseWindow(connection_id, id, msg)
|
||||
, m_frame(*this)
|
||||
{
|
||||
m_bounds = LG::Rect(0, 0, msg.width() + frame().left_border_size() + frame().right_border_size(), msg.height() + frame().top_border_size() + frame().bottom_border_size());
|
||||
m_content_bounds = LG::Rect(m_frame.left_border_size(), m_frame.top_border_size(), msg.width(), msg.height());
|
||||
m_content_bitmap = LG::PixelBitmap(m_buffer.data(), content_bounds().width(), content_bounds().height());
|
||||
|
||||
// Creating standard menubar directory entry.
|
||||
m_menubar_content.push_back(MenuDir(m_app_name, 0));
|
||||
m_menubar_content[0].add_item(PopupItem { PopupItem::InternalId, "Minimize others", [this](int) { WindowManager::the().minimize_windows([this](Window* win) { return win != this; }); } });
|
||||
m_menubar_content[0].add_item(PopupItem { PopupItem::InternalId, "Minimize", [this](int) { WindowManager::the().minimize_window(*this); } });
|
||||
m_menubar_content[0].add_item(PopupItem { PopupItem::InternalId, "Close", [this](int) { WindowManager::the().close_window(*this); } });
|
||||
}
|
||||
|
||||
Window::Window(Window&& win)
|
||||
: BaseWindow(std::move(win))
|
||||
, m_frame(*this, std::move(win.m_frame.control_panel_buttons()), std::move(win.m_frame.window_control_buttons()))
|
||||
, m_corner_mask(std::move(win.m_corner_mask))
|
||||
, m_menubar_content(std::move(win.m_menubar_content))
|
||||
{
|
||||
}
|
||||
|
||||
void Window::make_frame()
|
||||
{
|
||||
uint32_t x = m_bounds.min_x();
|
||||
uint32_t y = m_bounds.min_y();
|
||||
uint32_t content_width = m_content_bounds.width();
|
||||
uint32_t content_height = m_content_bounds.height();
|
||||
m_bounds = LG::Rect(x, y, content_width + frame().left_border_size() + frame().right_border_size(), content_height + frame().top_border_size() + frame().bottom_border_size());
|
||||
m_content_bounds = LG::Rect(x + m_frame.left_border_size(), y + m_frame.top_border_size(), content_width, content_height);
|
||||
m_frame.set_visible(true);
|
||||
}
|
||||
|
||||
void Window::make_frameless()
|
||||
{
|
||||
uint32_t x = m_bounds.min_x();
|
||||
uint32_t y = m_bounds.min_y();
|
||||
uint32_t content_width = m_content_bounds.width();
|
||||
uint32_t content_height = m_content_bounds.height();
|
||||
m_bounds = LG::Rect(x, y, content_width, content_height);
|
||||
m_content_bounds = LG::Rect(x, y, content_width, content_height);
|
||||
m_frame.set_visible(false);
|
||||
}
|
||||
|
||||
void Window::recalc_bounds(const LG::Size& size)
|
||||
{
|
||||
m_content_bounds.set_width(size.width());
|
||||
m_content_bounds.set_height(size.height());
|
||||
|
||||
m_bounds.set_width(size.width() + frame().left_border_size() + frame().right_border_size());
|
||||
m_bounds.set_height(size.height() + frame().top_border_size() + frame().bottom_border_size());
|
||||
}
|
||||
|
||||
void Window::did_size_change(const LG::Size& size)
|
||||
{
|
||||
recalc_bounds(size);
|
||||
}
|
||||
|
||||
void Window::on_style_change()
|
||||
{
|
||||
WindowManager::the().on_window_style_change(*this);
|
||||
}
|
||||
|
||||
void Window::on_menubar_change()
|
||||
{
|
||||
WindowManager::the().on_window_menubar_change(*this);
|
||||
}
|
||||
|
||||
} // namespace WinServer
|
||||
47
userland/servers/window_server/src/Target/Desktop/Window.h
Normal file
47
userland/servers/window_server/src/Target/Desktop/Window.h
Normal file
@@ -0,0 +1,47 @@
|
||||
#pragma once
|
||||
#include "../../Components/Base/BaseWindow.h"
|
||||
#include "../../Components/MenuBar/MenuItem.h"
|
||||
#include "../../IPC/Connection.h"
|
||||
#include "WindowFrame.h"
|
||||
#include <libfoundation/SharedBuffer.h>
|
||||
#include <libg/PixelBitmap.h>
|
||||
#include <libg/Rect.h>
|
||||
#include <sys/types.h>
|
||||
#include <utility>
|
||||
|
||||
namespace WinServer::Desktop {
|
||||
|
||||
class Window : public BaseWindow {
|
||||
public:
|
||||
Window(int connection_id, int id, CreateWindowMessage& msg);
|
||||
Window(Window&& win);
|
||||
|
||||
inline WindowFrame& frame() { return m_frame; }
|
||||
inline const WindowFrame& frame() const { return m_frame; }
|
||||
|
||||
inline const LG::CornerMask& corner_mask() const { return m_corner_mask; }
|
||||
|
||||
inline std::vector<MenuDir>& menubar_content() { return m_menubar_content; }
|
||||
inline const std::vector<MenuDir>& menubar_content() const { return m_menubar_content; }
|
||||
|
||||
void on_menubar_change();
|
||||
|
||||
virtual void did_app_title_change() override { m_frame.on_set_app_title(); }
|
||||
virtual void did_icon_path_change() override { m_frame.on_set_icon(); }
|
||||
virtual void did_size_change(const LG::Size& size) override;
|
||||
|
||||
inline void set_style(StatusBarStyle style) { m_frame.set_style(style), on_style_change(); }
|
||||
|
||||
void make_frame();
|
||||
void make_frameless();
|
||||
|
||||
private:
|
||||
void recalc_bounds(const LG::Size& size);
|
||||
void on_style_change();
|
||||
|
||||
WindowFrame m_frame;
|
||||
LG::CornerMask m_corner_mask { LG::CornerMask::SystemRadius, LG::CornerMask::NonMasked, LG::CornerMask::Masked };
|
||||
std::vector<MenuDir> m_menubar_content;
|
||||
};
|
||||
|
||||
} // namespace WinServer
|
||||
@@ -0,0 +1,232 @@
|
||||
#include "WindowFrame.h"
|
||||
#include "../../Components/Elements/Button.h"
|
||||
#include "../../Managers/WindowManager.h"
|
||||
#include "Window.h"
|
||||
#include <libg/Font.h>
|
||||
#include <libg/ImageLoaders/PNGLoader.h>
|
||||
#include <libg/Rect.h>
|
||||
#include <utility>
|
||||
|
||||
#define CONTROL_PANEL_CLOSE 0x0
|
||||
#define CONTROL_PANEL_MAXIMIZE 0x1
|
||||
#define CONTROL_PANEL_MINIMIZE 0x2
|
||||
|
||||
namespace WinServer::Desktop {
|
||||
|
||||
static const uint32_t s_close_button_glyph_data[10] = {
|
||||
0b1100000011,
|
||||
0b1110000111,
|
||||
0b0111001110,
|
||||
0b0011111100,
|
||||
0b0001111000,
|
||||
0b0001111000,
|
||||
0b0011111100,
|
||||
0b0111001110,
|
||||
0b1110000111,
|
||||
0b1100000011,
|
||||
};
|
||||
|
||||
static const uint32_t s_maximise_button_glyph_data[10] = {
|
||||
0b1111100000,
|
||||
0b1111000000,
|
||||
0b1110000000,
|
||||
0b1100000000,
|
||||
0b1000000000,
|
||||
0b0000000001,
|
||||
0b0000000011,
|
||||
0b0000000111,
|
||||
0b0000001111,
|
||||
0b0000011111
|
||||
};
|
||||
|
||||
static const uint32_t s_minimise_button_glyph_data[10] = {
|
||||
0b0000000000,
|
||||
0b0000000000,
|
||||
0b0000000000,
|
||||
0b0000000000,
|
||||
0b0000000000,
|
||||
0b0000000000,
|
||||
0b0000000000,
|
||||
0b0000000000,
|
||||
0b1111111111,
|
||||
0b1111111111
|
||||
};
|
||||
|
||||
WindowFrame::WindowFrame(Window& window)
|
||||
: m_window(window)
|
||||
, m_window_control_buttons()
|
||||
, m_control_panel_buttons()
|
||||
{
|
||||
set_style(StatusBarStyle::StandardLight);
|
||||
LG::GlyphMetrics metrics = {
|
||||
.width = 10,
|
||||
.height = 10,
|
||||
.top_bearing = 10,
|
||||
.left_bearing = 0,
|
||||
.baseline = 0,
|
||||
.advance = 10,
|
||||
.font_size = 10
|
||||
};
|
||||
|
||||
auto* close = new Button();
|
||||
close->set_icon(LG::Glyph(s_close_button_glyph_data, metrics, LG::Glyph::ConstDataMarker {}));
|
||||
auto* maximize = new Button();
|
||||
maximize->set_icon(LG::Glyph(s_maximise_button_glyph_data, metrics, LG::Glyph::ConstDataMarker {}));
|
||||
auto* minimize = new Button();
|
||||
minimize->set_icon(LG::Glyph(s_minimise_button_glyph_data, metrics, LG::Glyph::ConstDataMarker {}));
|
||||
|
||||
close->set_title_color(LG::Color(196, 128, 128));
|
||||
|
||||
m_window_control_buttons.push_back(close);
|
||||
m_window_control_buttons.push_back(maximize);
|
||||
m_window_control_buttons.push_back(minimize);
|
||||
}
|
||||
|
||||
WindowFrame::WindowFrame(Window& window, std::vector<Button*>&& control_panel_buttons, std::vector<Button*>&& window_control_buttons)
|
||||
: m_window(window)
|
||||
, m_window_control_buttons(std::move(window_control_buttons))
|
||||
, m_control_panel_buttons(std::move(control_panel_buttons))
|
||||
{
|
||||
}
|
||||
|
||||
void WindowFrame::on_set_app_title()
|
||||
{
|
||||
m_app_title_width = Helpers::text_width(m_window.app_title(), LG::Font::system_font());
|
||||
if (style().show_text()) {
|
||||
WinServer::Compositor::the().invalidate(bounds());
|
||||
}
|
||||
}
|
||||
|
||||
void WindowFrame::add_control(const std::string& title)
|
||||
{
|
||||
auto* new_control = new Button();
|
||||
new_control->set_title(title);
|
||||
m_control_panel_buttons.push_back(new_control);
|
||||
WinServer::Compositor::the().invalidate(bounds());
|
||||
}
|
||||
|
||||
void WindowFrame::draw(LG::Context& ctx)
|
||||
{
|
||||
if (!visible()) {
|
||||
return;
|
||||
}
|
||||
int x = m_window.bounds().min_x();
|
||||
int y = m_window.bounds().min_y();
|
||||
size_t width = m_window.bounds().width();
|
||||
size_t height = m_window.bounds().height();
|
||||
|
||||
int left_x = x + left_border_size();
|
||||
int right_x = x + width - right_border_size();
|
||||
int bottom_y = y + height - bottom_border_size();
|
||||
|
||||
// Drawing frame and shadings
|
||||
int shadow_spread = LG::Shading::SystemSpread;
|
||||
ctx.set_fill_color(style().color());
|
||||
ctx.fill_rounded(LG::Rect(x + left_border_size(), y + std_top_border_frame_size(), width - 2 * left_border_size(), top_border_size() - std_top_border_frame_size()), LG::CornerMask(4, true, false));
|
||||
ctx.set_fill_color(Color::Shadow);
|
||||
const auto shading_rect = LG::Rect(x + left_border_size(), y + std_top_border_frame_size(), width - 2 * left_border_size(), height - std_top_border_frame_size() - std_bottom_border_size());
|
||||
ctx.draw_box_shading(shading_rect, LG::Shading(LG::Shading::Type::Box, 0, shadow_spread), LG::CornerMask(LG::CornerMask::SystemRadius));
|
||||
|
||||
// Drawing labels, icons.
|
||||
// Drawing positions are calculated using a start of the frame.
|
||||
ctx.set_fill_color(m_text_colors[(int)active()]);
|
||||
if (style().show_text()) {
|
||||
Helpers::draw_text(ctx, { left_x + spacing(), y + text_y_offset() }, m_window.app_title(), LG::Font::system_font());
|
||||
}
|
||||
|
||||
int start_controls_offset = m_app_title_width + 2 * spacing();
|
||||
int start_controls = left_x + start_controls_offset;
|
||||
for (int i = 0; i < m_control_panel_buttons.size(); i++) {
|
||||
m_control_panel_buttons[i]->display(ctx, { start_controls, y + text_y_offset() });
|
||||
start_controls += spacing() + m_control_panel_buttons[i]->bounds().width();
|
||||
}
|
||||
|
||||
int start_buttons = right_x - spacing() - m_window_control_buttons[0]->bounds().width();
|
||||
for (int i = 0; i < m_window_control_buttons.size(); i++) {
|
||||
if (active() && i == 0) {
|
||||
ctx.set_fill_color(m_window_control_buttons[i]->title_color());
|
||||
} else {
|
||||
ctx.set_fill_color(m_text_colors[(int)active()]);
|
||||
}
|
||||
|
||||
m_window_control_buttons[i]->display(ctx, { start_buttons, y + button_y_offset() });
|
||||
start_buttons += -spacing() - m_window_control_buttons[i]->bounds().width();
|
||||
}
|
||||
}
|
||||
|
||||
void WindowFrame::invalidate(WinServer::Compositor& compositor) const
|
||||
{
|
||||
if (!visible()) {
|
||||
return;
|
||||
}
|
||||
int x = m_window.bounds().min_x();
|
||||
int y = m_window.bounds().min_y();
|
||||
size_t width = m_window.bounds().width();
|
||||
size_t height = m_window.bounds().height();
|
||||
int right_x = x + width - right_border_size();
|
||||
int bottom_y = y + height - bottom_border_size();
|
||||
compositor.invalidate(LG::Rect(x, y, width, top_border_size()));
|
||||
compositor.invalidate(LG::Rect(x, y, left_border_size(), height));
|
||||
compositor.invalidate(LG::Rect(right_x, y, right_border_size(), height));
|
||||
compositor.invalidate(LG::Rect(x, bottom_y, width, bottom_border_size()));
|
||||
}
|
||||
|
||||
void WindowFrame::receive_tap_event(const LG::Point<int>& tap)
|
||||
{
|
||||
// Calculating buttons' positions
|
||||
size_t width = m_window.bounds().width();
|
||||
int right_x = width - right_border_size();
|
||||
int start_buttons = right_x - spacing() - m_window_control_buttons[0]->bounds().width();
|
||||
for (int button_id = 0; button_id < m_window_control_buttons.size(); button_id++) {
|
||||
auto button_frame = m_window_control_buttons[button_id]->bounds();
|
||||
button_frame.offset_by(start_buttons, button_y_offset());
|
||||
if (button_frame.contains(tap)) {
|
||||
handle_control_panel_tap(button_id);
|
||||
return;
|
||||
}
|
||||
start_buttons += -spacing() - button_frame.width();
|
||||
}
|
||||
}
|
||||
|
||||
const LG::Rect WindowFrame::bounds() const
|
||||
{
|
||||
const auto& bounds = m_window.bounds();
|
||||
return LG::Rect(bounds.min_x(), bounds.min_y(), bounds.width(), top_border_size());
|
||||
}
|
||||
|
||||
void WindowFrame::handle_control_panel_tap(int button_id)
|
||||
{
|
||||
auto& wm = WindowManager::the();
|
||||
switch (button_id) {
|
||||
case CONTROL_PANEL_CLOSE:
|
||||
wm.close_window(m_window);
|
||||
break;
|
||||
case CONTROL_PANEL_MAXIMIZE:
|
||||
wm.maximize_window(m_window);
|
||||
break;
|
||||
case CONTROL_PANEL_MINIMIZE:
|
||||
wm.minimize_window(m_window);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void WindowFrame::set_style(StatusBarStyle ts)
|
||||
{
|
||||
m_style = ts;
|
||||
|
||||
if (m_style.dark_text()) {
|
||||
m_text_colors[0] = Color::InactiveText;
|
||||
m_text_colors[1] = LG::Color::DarkSystemText;
|
||||
} else {
|
||||
m_text_colors[0] = Color::InactiveText;
|
||||
m_text_colors[1] = LG::Color::LightSystemText;
|
||||
}
|
||||
}
|
||||
|
||||
void WindowFrame::on_set_icon()
|
||||
{
|
||||
}
|
||||
|
||||
} // namespace WinServer
|
||||
@@ -0,0 +1,87 @@
|
||||
#pragma once
|
||||
#include "../../Components/Elements/Button.h"
|
||||
#include "../../Constants/Colors.h"
|
||||
#include "../../IPC/Event.h"
|
||||
#include <libapi/window_server/MessageContent/MenuBar.h>
|
||||
#include <libfoundation/EventReceiver.h>
|
||||
#include <libg/Context.h>
|
||||
#include <libg/PixelBitmap.h>
|
||||
|
||||
namespace WinServer {
|
||||
class Compositor;
|
||||
}
|
||||
|
||||
namespace WinServer::Desktop {
|
||||
|
||||
class Window;
|
||||
|
||||
class WindowFrame {
|
||||
public:
|
||||
explicit WindowFrame(Window& window);
|
||||
WindowFrame(Window& window, std::vector<Button*>&& control_panel_buttons, std::vector<Button*>&& window_control_buttons);
|
||||
~WindowFrame() = default;
|
||||
|
||||
void draw(LG::Context&);
|
||||
static constexpr size_t std_app_header_size() { return 26; }
|
||||
static constexpr size_t std_top_border_frame_size() { return 4; }
|
||||
static constexpr size_t std_top_border_size() { return std_top_border_frame_size() + std_app_header_size(); }
|
||||
static constexpr size_t std_bottom_border_size() { return 4; }
|
||||
static constexpr size_t std_left_border_size() { return 4; }
|
||||
static constexpr size_t std_right_border_size() { return 4; }
|
||||
inline size_t top_border_size() const { return m_top_border_size; }
|
||||
inline size_t bottom_border_size() const { return std_bottom_border_size(); }
|
||||
inline size_t left_border_size() const { return std_left_border_size(); }
|
||||
inline size_t right_border_size() const { return std_right_border_size(); }
|
||||
|
||||
const LG::Rect bounds() const;
|
||||
|
||||
void receive_tap_event(const LG::Point<int>& tap);
|
||||
|
||||
void on_set_app_title();
|
||||
void add_control(const std::string& title);
|
||||
|
||||
inline std::vector<Button*>& window_control_buttons() { return m_window_control_buttons; }
|
||||
inline const std::vector<Button*>& window_control_buttons() const { return m_window_control_buttons; }
|
||||
|
||||
inline std::vector<Button*>& control_panel_buttons() { return m_control_panel_buttons; }
|
||||
inline const std::vector<Button*>& control_panel_buttons() const { return m_control_panel_buttons; }
|
||||
void handle_control_panel_tap(int button_id);
|
||||
|
||||
inline StatusBarStyle style() const { return m_style; }
|
||||
void set_style(StatusBarStyle ts);
|
||||
|
||||
void set_visible(bool visible)
|
||||
{
|
||||
m_top_border_size = visible ? std_top_border_size() : 0;
|
||||
m_visible = visible;
|
||||
}
|
||||
|
||||
bool visible() const { return m_visible; }
|
||||
void set_active(bool active) { m_active = active; }
|
||||
bool active() const { return m_active; }
|
||||
|
||||
void invalidate(WinServer::Compositor& compositor) const;
|
||||
|
||||
void on_set_icon();
|
||||
|
||||
static constexpr int spacing() { return 8; }
|
||||
static constexpr int icon_width() { return 12; }
|
||||
static constexpr int icon_y_offset() { return 7 + std_top_border_frame_size(); }
|
||||
static constexpr int text_y_offset() { return 9 + std_top_border_frame_size(); }
|
||||
static constexpr int button_y_offset() { return 8 + std_top_border_frame_size(); }
|
||||
|
||||
private:
|
||||
Window& m_window;
|
||||
std::vector<Button*> m_window_control_buttons;
|
||||
std::vector<Button*> m_control_panel_buttons;
|
||||
LG::Color m_text_colors[2];
|
||||
LG::Color m_color { LG::Color::LightSystemBackground };
|
||||
size_t m_top_border_size { std_top_border_size() };
|
||||
size_t m_app_title_width { 0 };
|
||||
bool m_visible { true };
|
||||
bool m_active { true };
|
||||
|
||||
StatusBarStyle m_style;
|
||||
};
|
||||
|
||||
} // namespace WinServer
|
||||
14
userland/servers/window_server/src/Target/Generic/Window.h
Normal file
14
userland/servers/window_server/src/Target/Generic/Window.h
Normal file
@@ -0,0 +1,14 @@
|
||||
#pragma once
|
||||
|
||||
#include "../Desktop/Window.h"
|
||||
#include "../Mobile/Window.h"
|
||||
|
||||
namespace WinServer {
|
||||
|
||||
#ifdef TARGET_DESKTOP
|
||||
using Window = Desktop::Window;
|
||||
#elif TARGET_MOBILE
|
||||
using Window = Mobile::Window;
|
||||
#endif
|
||||
|
||||
} // namespace WinServer
|
||||
25
userland/servers/window_server/src/Target/Mobile/Window.cpp
Normal file
25
userland/servers/window_server/src/Target/Mobile/Window.cpp
Normal file
@@ -0,0 +1,25 @@
|
||||
#include "Window.h"
|
||||
#include "../../Managers/WindowManager.h"
|
||||
#include <utility>
|
||||
|
||||
namespace WinServer::Mobile {
|
||||
|
||||
Window::Window(int connection_id, int id, CreateWindowMessage& msg)
|
||||
: BaseWindow(connection_id, id, msg)
|
||||
{
|
||||
m_bounds = LG::Rect(0, 0, msg.width(), msg.height());
|
||||
m_content_bounds = LG::Rect(0, 0, msg.width(), msg.height());
|
||||
m_content_bitmap = LG::PixelBitmap(m_buffer.data(), content_bounds().width(), content_bounds().height());
|
||||
}
|
||||
|
||||
Window::Window(Window&& win)
|
||||
: BaseWindow(std::move(win))
|
||||
{
|
||||
}
|
||||
|
||||
void Window::on_style_change()
|
||||
{
|
||||
WindowManager::the().on_window_style_change(*this);
|
||||
}
|
||||
|
||||
} // namespace WinServer
|
||||
27
userland/servers/window_server/src/Target/Mobile/Window.h
Normal file
27
userland/servers/window_server/src/Target/Mobile/Window.h
Normal file
@@ -0,0 +1,27 @@
|
||||
#pragma once
|
||||
#include "../../Components/Base/BaseWindow.h"
|
||||
#include "../../Components/MenuBar/MenuItem.h"
|
||||
#include "../../IPC/Connection.h"
|
||||
#include <libfoundation/SharedBuffer.h>
|
||||
#include <libg/PixelBitmap.h>
|
||||
#include <libg/Rect.h>
|
||||
#include <sys/types.h>
|
||||
#include <utility>
|
||||
|
||||
namespace WinServer::Mobile {
|
||||
|
||||
class Window : public BaseWindow {
|
||||
public:
|
||||
Window(int connection_id, int id, CreateWindowMessage& msg);
|
||||
Window(Window&& win);
|
||||
|
||||
inline void set_style(StatusBarStyle ts) { m_style = ts, on_style_change(); }
|
||||
inline StatusBarStyle style() { return m_style; }
|
||||
|
||||
private:
|
||||
void on_style_change();
|
||||
|
||||
StatusBarStyle m_style { StatusBarStyle::StandardLight };
|
||||
};
|
||||
|
||||
} // namespace WinServer
|
||||
Reference in New Issue
Block a user