wind: Remove special window attributes and add different window layers.
All checks were successful
Build and test / build (push) Successful in 1m38s
All checks were successful
Build and test / build (push) Successful in 1m38s
Two layers are accessible to all apps: global and global_top (for popups and similar windows). Three other layers are accessible to privileged clients (background, system and lock), for things that need to be on a different level than user apps, like the taskbar, system popups, menus and the lock screen.
This commit is contained in:
parent
ccef3e2069
commit
fb3333a086
@ -125,7 +125,7 @@ Result<int> luna_main(int, char**)
|
||||
app.set_main_window(window);
|
||||
|
||||
window->set_background(TASKBAR_COLOR);
|
||||
window->set_special_attributes(ui::UNFOCUSEABLE);
|
||||
window->set_layer(ui::Layer::Background);
|
||||
|
||||
ui::HorizontalLayout layout(ui::Margins { 0, 0, 0, 0 }, ui::AdjustHeight::Yes, ui::AdjustWidth::No);
|
||||
window->set_main_widget(layout);
|
||||
|
@ -65,7 +65,7 @@ namespace ui
|
||||
|
||||
void close();
|
||||
|
||||
void set_special_attributes(WindowAttributes attributes);
|
||||
void set_layer(Layer layer);
|
||||
|
||||
Result<void> draw();
|
||||
Result<ui::EventResult> handle_mouse_leave();
|
||||
|
@ -25,7 +25,7 @@ namespace ui
|
||||
CLOSE_WINDOW_ID,
|
||||
GET_SCREEN_RECT_ID,
|
||||
SET_TITLEBAR_HEIGHT_ID,
|
||||
SET_SPECIAL_WINDOW_ATTRIBUTES_ID,
|
||||
SET_WINDOW_LAYER_ID,
|
||||
};
|
||||
|
||||
struct CreateWindowRequest
|
||||
@ -81,16 +81,20 @@ namespace ui
|
||||
int height;
|
||||
};
|
||||
|
||||
enum WindowAttributes : u8
|
||||
enum Layer : u8
|
||||
{
|
||||
UNFOCUSEABLE = 1,
|
||||
Background,
|
||||
Global,
|
||||
GlobalTop,
|
||||
System,
|
||||
Lock
|
||||
};
|
||||
|
||||
struct SetSpecialWindowAttributesRequest
|
||||
struct SetWindowLayer
|
||||
{
|
||||
static constexpr u8 ID = SET_SPECIAL_WINDOW_ATTRIBUTES_ID;
|
||||
static constexpr u8 ID = SET_WINDOW_LAYER_ID;
|
||||
|
||||
int window;
|
||||
WindowAttributes attributes;
|
||||
Layer layer;
|
||||
};
|
||||
}
|
||||
|
@ -115,11 +115,11 @@ namespace ui
|
||||
app.unregister_window(this, {});
|
||||
}
|
||||
|
||||
void Window::set_special_attributes(WindowAttributes attributes)
|
||||
void Window::set_layer(Layer layer)
|
||||
{
|
||||
ui::SetSpecialWindowAttributesRequest request;
|
||||
ui::SetWindowLayer request;
|
||||
request.window = m_id;
|
||||
request.attributes = attributes;
|
||||
request.layer = layer;
|
||||
App::the().client().send_async(request);
|
||||
}
|
||||
|
||||
|
@ -11,6 +11,8 @@ set(SOURCES
|
||||
Keyboard.cpp
|
||||
Keyboard.h
|
||||
Client.h
|
||||
Layer.cpp
|
||||
Layer.h
|
||||
)
|
||||
|
||||
add_executable(wind ${SOURCES})
|
||||
|
@ -1,4 +1,5 @@
|
||||
#include "IPC.h"
|
||||
#include "Layer.h"
|
||||
#include "Mouse.h"
|
||||
#include "Screen.h"
|
||||
#include <luna/Alignment.h>
|
||||
@ -47,7 +48,7 @@ static Result<void> handle_create_window_message(Client& client)
|
||||
}
|
||||
|
||||
auto guard = make_scope_guard([window] {
|
||||
g_windows.remove(window);
|
||||
window->layer->windows.remove(window);
|
||||
delete window;
|
||||
});
|
||||
|
||||
@ -120,7 +121,7 @@ static Result<void> handle_close_window_message(Client& client)
|
||||
|
||||
auto* window = client.windows[request.window];
|
||||
client.windows[request.window] = nullptr;
|
||||
g_windows.remove(window);
|
||||
window->layer->windows.remove(window);
|
||||
Mouse::the().window_did_close(window);
|
||||
delete window;
|
||||
|
||||
@ -160,22 +161,40 @@ static Result<void> handle_set_titlebar_height_message(Client& client)
|
||||
return {};
|
||||
}
|
||||
|
||||
static Result<void> handle_set_special_window_attributes_message(Client& client)
|
||||
static Result<void> handle_set_window_layer_message(Client& client)
|
||||
{
|
||||
ui::SetSpecialWindowAttributesRequest request;
|
||||
ui::SetWindowLayer request;
|
||||
if (!TRY(client.conn->read_message(request))) return {};
|
||||
|
||||
if (!client.privileged)
|
||||
if (request.layer != ui::Layer::Global && request.layer != ui::Layer::GlobalTop && !client.privileged)
|
||||
{
|
||||
os::eprintln(
|
||||
"wind: Unprivileged client trying to call privileged request (SetSpecialWindowAttributes), disconnecting!");
|
||||
os::eprintln("wind: Unprivileged client trying to set window layer to a privileged layer, disconnecting!");
|
||||
client.should_be_disconnected = true;
|
||||
return {};
|
||||
}
|
||||
|
||||
CHECK_WINDOW_ID(request, "SetSpecialWindowAttributes");
|
||||
CHECK_WINDOW_ID(request, "SetWindowLayer");
|
||||
|
||||
client.windows[request.window]->attributes = request.attributes;
|
||||
auto* window = client.windows[request.window];
|
||||
|
||||
window->layer->windows.remove(window);
|
||||
|
||||
switch (request.layer)
|
||||
{
|
||||
case ui::Layer::Background: window->layer = &l_background; break;
|
||||
case ui::Layer::Global: window->layer = &l_global; break;
|
||||
case ui::Layer::GlobalTop: window->layer = &l_global_top; break;
|
||||
case ui::Layer::System: window->layer = &l_system; break;
|
||||
case ui::Layer::Lock: window->layer = &l_lock; break;
|
||||
default: {
|
||||
window->layer->windows.append(window);
|
||||
os::eprintln("wind: Client trying to set window layer to an invalid layer, disconnecting!");
|
||||
client.should_be_disconnected = true;
|
||||
return {};
|
||||
}
|
||||
}
|
||||
|
||||
window->layer->windows.append(window);
|
||||
|
||||
return {};
|
||||
}
|
||||
@ -194,7 +213,7 @@ namespace wind
|
||||
case ui::CLOSE_WINDOW_ID: handle_close_window_message(client); break;
|
||||
case ui::GET_SCREEN_RECT_ID: handle_get_screen_rect_message(client); break;
|
||||
case ui::SET_TITLEBAR_HEIGHT_ID: handle_set_titlebar_height_message(client); break;
|
||||
case ui::SET_SPECIAL_WINDOW_ATTRIBUTES_ID: handle_set_special_window_attributes_message(client); break;
|
||||
case ui::SET_WINDOW_LAYER_ID: handle_set_window_layer_message(client); break;
|
||||
default: os::eprintln("wind: Invalid IPC message from client!"); return;
|
||||
}
|
||||
}
|
||||
|
79
gui/wind/Layer.cpp
Normal file
79
gui/wind/Layer.cpp
Normal file
@ -0,0 +1,79 @@
|
||||
#include "Layer.h"
|
||||
#include "Client.h"
|
||||
#include "Window.h"
|
||||
|
||||
Layer l_background;
|
||||
Layer l_global;
|
||||
Layer l_global_top;
|
||||
Layer l_system;
|
||||
Layer l_lock;
|
||||
|
||||
constexpr int NUM_LAYERS = 5;
|
||||
|
||||
static Layer* const layers_front_to_back[NUM_LAYERS] = { &l_lock, &l_system, &l_global_top, &l_global, &l_background };
|
||||
static Layer* const layers_back_to_front[NUM_LAYERS] = { &l_background, &l_global, &l_global_top, &l_system, &l_lock };
|
||||
|
||||
Window* Layer::focused_window()
|
||||
{
|
||||
for (int i = 0; i < NUM_LAYERS; i++)
|
||||
{
|
||||
Layer* l = layers_front_to_back[i];
|
||||
if (l->windows.last().has_value()) return l->windows.last().value();
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
void Layer::draw_all_windows(ui::Canvas& canvas)
|
||||
{
|
||||
for (int i = 0; i < NUM_LAYERS; i++)
|
||||
{
|
||||
Layer* l = layers_back_to_front[i];
|
||||
for (Window* w : l->windows) { w->draw(canvas); }
|
||||
}
|
||||
}
|
||||
|
||||
Window* Layer::propagate_mouse_event(ui::Point position, u8 buttons)
|
||||
{
|
||||
for (int i = 0; i < NUM_LAYERS; i++)
|
||||
{
|
||||
Layer* l = layers_front_to_back[i];
|
||||
for (Window* window = l->windows.last().value_or(nullptr); window;
|
||||
window = l->windows.previous(window).value_or(nullptr))
|
||||
{
|
||||
if (window->surface.contains(position))
|
||||
{
|
||||
ui::MouseEventRequest request;
|
||||
request.window = window->id;
|
||||
request.position = window->surface.relative(position);
|
||||
request.buttons = buttons;
|
||||
window->client->conn->send_async(request);
|
||||
return window;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
Window* Layer::propagate_drag_event(ui::Point position)
|
||||
{
|
||||
for (int i = 0; i < NUM_LAYERS; i++)
|
||||
{
|
||||
Layer* l = layers_front_to_back[i];
|
||||
for (Window* window = l->windows.last().value_or(nullptr); window;
|
||||
window = l->windows.previous(window).value_or(nullptr))
|
||||
{
|
||||
if (window->surface.contains(position))
|
||||
{
|
||||
window->focus();
|
||||
|
||||
if (window->surface.absolute(window->titlebar).contains(position)) return window;
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
}
|
20
gui/wind/Layer.h
Normal file
20
gui/wind/Layer.h
Normal file
@ -0,0 +1,20 @@
|
||||
#pragma once
|
||||
#include "Window.h"
|
||||
#include <luna/LinkedList.h>
|
||||
#include <ui/Canvas.h>
|
||||
|
||||
struct Layer
|
||||
{
|
||||
LinkedList<Window> windows;
|
||||
|
||||
static Window* focused_window();
|
||||
static void draw_all_windows(ui::Canvas& canvas);
|
||||
static Window* propagate_mouse_event(ui::Point position, u8 buttons);
|
||||
static Window* propagate_drag_event(ui::Point position);
|
||||
};
|
||||
|
||||
extern Layer l_background;
|
||||
extern Layer l_global;
|
||||
extern Layer l_global_top;
|
||||
extern Layer l_system;
|
||||
extern Layer l_lock;
|
@ -1,5 +1,6 @@
|
||||
#include "Mouse.h"
|
||||
#include "Client.h"
|
||||
#include "Layer.h"
|
||||
#include <os/File.h>
|
||||
#include <os/IPC.h>
|
||||
#include <ui/Image.h>
|
||||
@ -57,45 +58,17 @@ void Mouse::update(const moon::MousePacket& packet)
|
||||
|
||||
else if ((packet.buttons & moon::MouseButton::Left) && !m_dragging_window)
|
||||
{
|
||||
// Iterate from the end of the list, since windows at the beginning are stacked at the bottom and windows at the
|
||||
// top are at the end.
|
||||
for (Window* window = g_windows.last().value_or(nullptr); window;
|
||||
window = g_windows.previous(window).value_or(nullptr))
|
||||
{
|
||||
if (window->surface.contains(m_position))
|
||||
{
|
||||
if (!(window->attributes & ui::UNFOCUSEABLE)) window->focus();
|
||||
|
||||
if (window->surface.absolute(window->titlebar).contains(m_position))
|
||||
if (auto* window = Layer::propagate_drag_event(m_position))
|
||||
{
|
||||
m_dragging_window = window;
|
||||
m_initial_drag_position = window->surface.relative(m_position);
|
||||
os::println("Started drag: window at (%d,%d,%d,%d) with offset (%d,%d)", window->surface.pos.x,
|
||||
window->surface.pos.y, window->surface.width, window->surface.height,
|
||||
m_initial_drag_position.x, m_initial_drag_position.y);
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
window->surface.pos.y, window->surface.width, window->surface.height, m_initial_drag_position.x,
|
||||
m_initial_drag_position.y);
|
||||
}
|
||||
}
|
||||
|
||||
Window* new_active_window = nullptr;
|
||||
|
||||
for (Window* window = g_windows.last().value_or(nullptr); window;
|
||||
window = g_windows.previous(window).value_or(nullptr))
|
||||
{
|
||||
if (window->surface.contains(m_position))
|
||||
{
|
||||
ui::MouseEventRequest request;
|
||||
request.window = window->id;
|
||||
request.position = window->surface.relative(m_position);
|
||||
request.buttons = packet.buttons;
|
||||
window->client->conn->send_async(request);
|
||||
new_active_window = window;
|
||||
break;
|
||||
}
|
||||
}
|
||||
Window* new_active_window = Layer::propagate_mouse_event(m_position, packet.buttons);
|
||||
|
||||
if (m_active_window != new_active_window)
|
||||
{
|
||||
|
@ -1,12 +1,11 @@
|
||||
#include "Window.h"
|
||||
#include "Layer.h"
|
||||
#include <luna/Utf8.h>
|
||||
#include <os/File.h>
|
||||
#include <sys/mman.h>
|
||||
#include <ui/Font.h>
|
||||
#include <ui/Image.h>
|
||||
|
||||
LinkedList<Window> g_windows;
|
||||
|
||||
void Window::draw(ui::Canvas& screen)
|
||||
{
|
||||
dirty = false;
|
||||
@ -18,15 +17,16 @@ void Window::draw(ui::Canvas& screen)
|
||||
void Window::focus()
|
||||
{
|
||||
// Bring the window to the front of the list.
|
||||
g_windows.remove(this);
|
||||
g_windows.append(this);
|
||||
layer->windows.remove(this);
|
||||
layer->windows.append(this);
|
||||
}
|
||||
|
||||
Window::Window(ui::Rect r, RefString&& n) : surface(r), name(move(n))
|
||||
{
|
||||
auto font = ui::Font::default_font();
|
||||
titlebar = ui::Rect { 0, 0, 0, 0 };
|
||||
g_windows.append(this);
|
||||
l_global.windows.append(this);
|
||||
layer = &l_global;
|
||||
}
|
||||
|
||||
Window::~Window()
|
||||
|
@ -7,6 +7,7 @@
|
||||
#include <ui/ipc/Server.h>
|
||||
|
||||
struct Client;
|
||||
struct Layer;
|
||||
|
||||
struct Window : public LinkedListNode<Window>
|
||||
{
|
||||
@ -17,8 +18,8 @@ struct Window : public LinkedListNode<Window>
|
||||
RefString shm_path;
|
||||
bool dirty { false };
|
||||
Client* client;
|
||||
Layer* layer;
|
||||
int id;
|
||||
ui::WindowAttributes attributes { 0 };
|
||||
|
||||
Window(ui::Rect, RefString&&);
|
||||
~Window();
|
||||
@ -27,5 +28,3 @@ struct Window : public LinkedListNode<Window>
|
||||
|
||||
void draw(ui::Canvas& screen);
|
||||
};
|
||||
|
||||
extern LinkedList<Window> g_windows;
|
||||
|
@ -1,6 +1,7 @@
|
||||
#define CLIENT_IMPLEMENTATION
|
||||
#include "Client.h"
|
||||
#include "Keyboard.h"
|
||||
#include "Layer.h"
|
||||
#include "Mouse.h"
|
||||
#include "Screen.h"
|
||||
#include "Window.h"
|
||||
@ -23,37 +24,6 @@ static constexpr uid_t WIND_USER_ID = 2;
|
||||
static constexpr gid_t WIND_GROUP_ID = 2;
|
||||
static constexpr gid_t WSYS_GROUP_ID = 3;
|
||||
|
||||
static void debug(const Vector<OwnedPtr<Client>>& clients)
|
||||
{
|
||||
os::println("--- wind: DEBUG OUTPUT ---");
|
||||
|
||||
os::println("-- wind: Listing clients --");
|
||||
|
||||
for (const auto& client : clients)
|
||||
{
|
||||
os::println("Client with fd %d, owns %zu windows", client->conn->fd(), client->windows.size());
|
||||
}
|
||||
|
||||
os::println("-- wind: Listing windows --");
|
||||
|
||||
for (const auto& window : g_windows)
|
||||
{
|
||||
os::println("Window of client (fd %d), id %d, %sdirty (\"%s\") (%d,%d,%d,%d)", window->client->conn->fd(),
|
||||
window->id, window->dirty ? "" : "not ", window->name.chars(), window->surface.pos.x,
|
||||
window->surface.pos.y, window->surface.width, window->surface.height);
|
||||
}
|
||||
|
||||
os::println("-- wind: Listing processes --");
|
||||
|
||||
system("ps");
|
||||
|
||||
os::println("-- wind: Listing memory usage --");
|
||||
|
||||
system("free -h");
|
||||
|
||||
os::println("--- wind: END DEBUG OUTPUT ---");
|
||||
}
|
||||
|
||||
Result<int> luna_main(int argc, char** argv)
|
||||
{
|
||||
srand((unsigned)time(NULL));
|
||||
@ -133,7 +103,7 @@ Result<int> luna_main(int argc, char** argv)
|
||||
while (1)
|
||||
{
|
||||
screen.canvas().fill(background);
|
||||
for (auto* window : g_windows) window->draw(screen.canvas());
|
||||
Layer::draw_all_windows(screen.canvas());
|
||||
mouse_pointer.draw(screen.canvas());
|
||||
screen.sync();
|
||||
|
||||
@ -153,11 +123,9 @@ Result<int> luna_main(int argc, char** argv)
|
||||
{
|
||||
moon::KeyboardPacket packet;
|
||||
TRY(keyboard->read_typed(packet));
|
||||
if (!packet.released && packet.key == moon::K_Tab) debug(clients);
|
||||
auto request = wind::Keyboard::decode_keyboard_event((moon::KeyCode)packet.key, packet.released);
|
||||
if (g_windows.last().has_value())
|
||||
if (auto* window = Layer::focused_window())
|
||||
{
|
||||
auto* window = g_windows.last().value();
|
||||
request.window = window->id;
|
||||
window->client->conn->send_async(request);
|
||||
}
|
||||
@ -198,7 +166,7 @@ Result<int> luna_main(int argc, char** argv)
|
||||
{
|
||||
if (window)
|
||||
{
|
||||
g_windows.remove(window);
|
||||
window->layer->windows.remove(window);
|
||||
mouse_pointer.window_did_close(window);
|
||||
delete window;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user