Compare commits

..

No commits in common. "c2b6ba0d5a35e3c762bedb4ed8c65a5d2cf32bc3" and "a1ab44d39fd14a79f9cf5e3bd3155aecabf28b9d" have entirely different histories.

52 changed files with 219 additions and 1682 deletions

View File

@ -141,7 +141,7 @@ namespace BAN
};
private:
static constexpr size_t m_size = sizeof(void*) * 8;
static constexpr size_t m_size = sizeof(void*) * 5;
alignas(CallableBase) uint8_t m_storage[m_size] { 0 };
};

View File

@ -9,7 +9,7 @@ namespace BAN
{
template<typename It>
constexpr It next(It it, size_t count)
It next(It it, size_t count)
{
for (size_t i = 0; i < count; i++)
++it;
@ -18,13 +18,13 @@ namespace BAN
template<typename It>
requires requires(It it, size_t n) { requires is_same_v<decltype(it + n), It>; }
constexpr It next(It it, size_t count)
It next(It it, size_t count)
{
return it + count;
}
template<typename It>
constexpr It prev(It it, size_t count)
It prev(It it, size_t count)
{
for (size_t i = 0; i < count; i++)
--it;
@ -33,13 +33,13 @@ namespace BAN
template<typename It>
requires requires(It it, size_t n) { requires is_same_v<decltype(it - n), It>; }
constexpr It prev(It it, size_t count)
It prev(It it, size_t count)
{
return it - count;
}
template<typename It>
constexpr size_t distance(It it1, It it2)
size_t distance(It it1, It it2)
{
size_t dist = 0;
while (it1 != it2)
@ -52,7 +52,7 @@ namespace BAN
template<typename It>
requires requires(It it1, It it2) { requires is_integral_v<decltype(it2 - it1)>; }
constexpr size_t distance(It it1, It it2)
size_t distance(It it1, It it2)
{
return it2 - it1;
}
@ -64,109 +64,109 @@ namespace BAN
using value_type = T;
public:
constexpr IteratorSimpleGeneral() = default;
IteratorSimpleGeneral() = default;
template<bool CONST2, typename = enable_if_t<CONST2 == CONST || CONST>>
constexpr IteratorSimpleGeneral(const IteratorSimpleGeneral<T, Container, CONST2>& other)
IteratorSimpleGeneral(const IteratorSimpleGeneral<T, Container, CONST2>& other)
: m_pointer(other.m_pointer)
, m_valid(other.m_valid)
{
}
constexpr const T& operator*() const
const T& operator*() const
{
ASSERT(m_pointer);
return *m_pointer;
}
template<bool CONST2 = CONST>
constexpr enable_if_t<!CONST2, T&> operator*()
enable_if_t<!CONST2, T&> operator*()
{
ASSERT(*this);
ASSERT(m_pointer);
return *m_pointer;
}
constexpr const T* operator->() const
const T* operator->() const
{
ASSERT(*this);
ASSERT(m_pointer);
return m_pointer;
}
template<bool CONST2 = CONST>
constexpr enable_if_t<!CONST2, T*> operator->()
enable_if_t<!CONST2, T*> operator->()
{
ASSERT(*this);
ASSERT(m_pointer);
return m_pointer;
}
constexpr IteratorSimpleGeneral& operator++()
IteratorSimpleGeneral& operator++()
{
ASSERT(*this);
ASSERT(m_pointer);
++m_pointer;
return *this;
}
constexpr IteratorSimpleGeneral operator++(int)
IteratorSimpleGeneral operator++(int)
{
auto temp = *this;
++(*this);
return temp;
}
constexpr IteratorSimpleGeneral& operator--()
IteratorSimpleGeneral& operator--()
{
ASSERT(*this);
ASSERT(m_pointer);
--m_pointer;
return *this;
}
constexpr IteratorSimpleGeneral operator--(int)
IteratorSimpleGeneral operator--(int)
{
auto temp = *this;
--(*this);
return temp;
}
constexpr size_t operator-(const IteratorSimpleGeneral& other) const
size_t operator-(const IteratorSimpleGeneral& other) const
{
ASSERT(*this && other);
return m_pointer - other.m_pointer;
}
constexpr IteratorSimpleGeneral operator+(size_t offset) const
IteratorSimpleGeneral operator+(size_t offset) const
{
return IteratorSimpleGeneral(m_pointer + offset);
}
constexpr IteratorSimpleGeneral operator-(size_t offset) const
IteratorSimpleGeneral operator-(size_t offset) const
{
return IteratorSimpleGeneral(m_pointer - offset);
}
constexpr bool operator<(const IteratorSimpleGeneral& other) const
bool operator<(const IteratorSimpleGeneral& other) const
{
ASSERT(*this);
return m_pointer < other.m_pointer;
}
constexpr bool operator==(const IteratorSimpleGeneral& other) const
bool operator==(const IteratorSimpleGeneral& other) const
{
ASSERT(*this);
return m_pointer == other.m_pointer;
}
constexpr bool operator!=(const IteratorSimpleGeneral& other) const
bool operator!=(const IteratorSimpleGeneral& other) const
{
ASSERT(*this);
return !(*this == other);
}
constexpr explicit operator bool() const
explicit operator bool() const
{
return m_valid;
}
private:
constexpr IteratorSimpleGeneral(maybe_const_t<CONST, T>* pointer)
IteratorSimpleGeneral(maybe_const_t<CONST, T>* pointer)
: m_pointer(pointer)
, m_valid(true)
{
@ -193,16 +193,16 @@ namespace BAN
using value_type = T;
public:
constexpr IteratorDoubleGeneral() = default;
IteratorDoubleGeneral() = default;
template<bool CONST2, typename = enable_if_t<CONST2 == CONST || CONST>>
constexpr IteratorDoubleGeneral(const IteratorDoubleGeneral<T, OuterContainer, InnerContainer, Container, CONST2>& other)
IteratorDoubleGeneral(const IteratorDoubleGeneral<T, OuterContainer, InnerContainer, Container, CONST2>& other)
: m_outer_end(other.m_outer_end)
, m_outer_current(other.m_outer_current)
, m_inner_current(other.m_inner_current)
{
}
constexpr const T& operator*() const
const T& operator*() const
{
ASSERT(*this);
ASSERT(m_outer_current != m_outer_end);
@ -210,7 +210,7 @@ namespace BAN
return m_inner_current.operator*();
}
template<bool CONST2 = CONST>
constexpr enable_if_t<!CONST2, T&> operator*()
enable_if_t<!CONST2, T&> operator*()
{
ASSERT(*this);
ASSERT(m_outer_current != m_outer_end);
@ -218,7 +218,7 @@ namespace BAN
return m_inner_current.operator*();
}
constexpr const T* operator->() const
const T* operator->() const
{
ASSERT(*this);
ASSERT(m_outer_current != m_outer_end);
@ -226,7 +226,7 @@ namespace BAN
return m_inner_current.operator->();
}
template<bool CONST2 = CONST>
constexpr enable_if_t<!CONST2, T*> operator->()
enable_if_t<!CONST2, T*> operator->()
{
ASSERT(*this);
ASSERT(m_outer_current != m_outer_end);
@ -234,7 +234,7 @@ namespace BAN
return m_inner_current.operator->();
}
constexpr IteratorDoubleGeneral& operator++()
IteratorDoubleGeneral& operator++()
{
ASSERT(*this);
ASSERT(m_outer_current != m_outer_end);
@ -243,14 +243,14 @@ namespace BAN
find_valid_or_end();
return *this;
}
constexpr IteratorDoubleGeneral operator++(int)
IteratorDoubleGeneral operator++(int)
{
auto temp = *this;
++(*this);
return temp;
}
constexpr bool operator==(const IteratorDoubleGeneral& other) const
bool operator==(const IteratorDoubleGeneral& other) const
{
ASSERT(*this && other);
if (m_outer_end != other.m_outer_end)
@ -262,18 +262,18 @@ namespace BAN
ASSERT(m_inner_current && other.m_inner_current);
return m_inner_current == other.m_inner_current;
}
constexpr bool operator!=(const IteratorDoubleGeneral& other) const
bool operator!=(const IteratorDoubleGeneral& other) const
{
return !(*this == other);
}
constexpr explicit operator bool() const
explicit operator bool() const
{
return !!m_outer_current;
}
private:
constexpr IteratorDoubleGeneral(const OuterIterator& outer_end, const OuterIterator& outer_current)
IteratorDoubleGeneral(const OuterIterator& outer_end, const OuterIterator& outer_current)
: m_outer_end(outer_end)
, m_outer_current(outer_current)
{
@ -284,7 +284,7 @@ namespace BAN
}
}
constexpr IteratorDoubleGeneral(const OuterIterator& outer_end, const OuterIterator& outer_current, const InnerIterator& inner_current)
IteratorDoubleGeneral(const OuterIterator& outer_end, const OuterIterator& outer_current, const InnerIterator& inner_current)
: m_outer_end(outer_end)
, m_outer_current(outer_current)
, m_inner_current(inner_current)
@ -292,7 +292,7 @@ namespace BAN
find_valid_or_end();
}
constexpr void find_valid_or_end()
void find_valid_or_end()
{
while (m_inner_current == m_outer_current->end())
{
@ -303,8 +303,8 @@ namespace BAN
}
}
constexpr OuterIterator outer_current() { return m_outer_current; }
constexpr InnerIterator inner_current() { return m_inner_current; }
OuterIterator outer_current() { return m_outer_current; }
InnerIterator inner_current() { return m_inner_current; }
private:
OuterIterator m_outer_end;

View File

@ -13,35 +13,35 @@ namespace BAN
class Optional
{
public:
constexpr Optional();
constexpr Optional(Optional&&);
constexpr Optional(const Optional&);
constexpr Optional(const T&);
constexpr Optional(T&&);
Optional();
Optional(Optional&&);
Optional(const Optional&);
Optional(const T&);
Optional(T&&);
template<typename... Args>
constexpr Optional(Args&&...);
Optional(Args&&...);
~Optional();
constexpr Optional& operator=(Optional&&);
constexpr Optional& operator=(const Optional&);
Optional& operator=(Optional&&);
Optional& operator=(const Optional&);
template<typename... Args>
constexpr Optional& emplace(Args&&...);
Optional& emplace(Args&&...);
constexpr T* operator->();
constexpr const T* operator->() const;
T* operator->();
const T* operator->() const;
constexpr T& operator*();
constexpr const T& operator*() const;
T& operator*();
const T& operator*() const;
constexpr bool has_value() const;
bool has_value() const;
constexpr T release_value();
constexpr T& value();
constexpr const T& value() const;
T release_value();
T& value();
const T& value() const;
constexpr void clear();
void clear();
private:
alignas(T) uint8_t m_storage[sizeof(T)];
@ -49,12 +49,12 @@ namespace BAN
};
template<typename T>
constexpr Optional<T>::Optional()
Optional<T>::Optional()
: m_has_value(false)
{}
template<typename T>
constexpr Optional<T>::Optional(Optional<T>&& other)
Optional<T>::Optional(Optional<T>&& other)
: m_has_value(other.has_value())
{
if (other.has_value())
@ -62,7 +62,7 @@ namespace BAN
}
template<typename T>
constexpr Optional<T>::Optional(const Optional<T>& other)
Optional<T>::Optional(const Optional<T>& other)
: m_has_value(other.has_value())
{
if (other.has_value())
@ -70,14 +70,14 @@ namespace BAN
}
template<typename T>
constexpr Optional<T>::Optional(const T& value)
Optional<T>::Optional(const T& value)
: m_has_value(true)
{
new (m_storage) T(value);
}
template<typename T>
constexpr Optional<T>::Optional(T&& value)
Optional<T>::Optional(T&& value)
: m_has_value(true)
{
new (m_storage) T(move(value));
@ -85,7 +85,7 @@ namespace BAN
template<typename T>
template<typename... Args>
constexpr Optional<T>::Optional(Args&&... args)
Optional<T>::Optional(Args&&... args)
: m_has_value(true)
{
new (m_storage) T(forward<Args>(args)...);
@ -98,7 +98,7 @@ namespace BAN
}
template<typename T>
constexpr Optional<T>& Optional<T>::operator=(Optional&& other)
Optional<T>& Optional<T>::operator=(Optional&& other)
{
clear();
m_has_value = other.has_value();
@ -108,7 +108,7 @@ namespace BAN
}
template<typename T>
constexpr Optional<T>& Optional<T>::operator=(const Optional& other)
Optional<T>& Optional<T>::operator=(const Optional& other)
{
clear();
m_has_value = other.has_value();
@ -119,7 +119,7 @@ namespace BAN
template<typename T>
template<typename... Args>
constexpr Optional<T>& Optional<T>::emplace(Args&&... args)
Optional<T>& Optional<T>::emplace(Args&&... args)
{
clear();
m_has_value = true;
@ -128,41 +128,41 @@ namespace BAN
}
template<typename T>
constexpr T* Optional<T>::operator->()
T* Optional<T>::operator->()
{
ASSERT(has_value());
return &value();
}
template<typename T>
constexpr const T* Optional<T>::operator->() const
const T* Optional<T>::operator->() const
{
ASSERT(has_value());
return &value();
}
template<typename T>
constexpr T& Optional<T>::operator*()
T& Optional<T>::operator*()
{
ASSERT(has_value());
return value();
}
template<typename T>
constexpr const T& Optional<T>::operator*() const
const T& Optional<T>::operator*() const
{
ASSERT(has_value());
return value();
}
template<typename T>
constexpr bool Optional<T>::has_value() const
bool Optional<T>::has_value() const
{
return m_has_value;
}
template<typename T>
constexpr T Optional<T>::release_value()
T Optional<T>::release_value()
{
ASSERT(has_value());
T released_value = move(value());
@ -172,21 +172,21 @@ namespace BAN
}
template<typename T>
constexpr T& Optional<T>::value()
T& Optional<T>::value()
{
ASSERT(has_value());
return (T&)m_storage;
}
template<typename T>
constexpr const T& Optional<T>::value() const
const T& Optional<T>::value() const
{
ASSERT(has_value());
return (const T&)m_storage;
}
template<typename T>
constexpr void Optional<T>::clear()
void Optional<T>::clear()
{
if (m_has_value)
value().~T();

View File

@ -124,9 +124,6 @@ namespace BAN
T* operator->() { return ptr(); }
const T* operator->() const { return ptr(); }
bool operator==(RefPtr other) const { return m_pointer == other.m_pointer; }
bool operator!=(RefPtr other) const { return m_pointer != other.m_pointer; }
bool empty() const { return m_pointer == nullptr; }
operator bool() const { return m_pointer; }

View File

@ -16,44 +16,40 @@ namespace BAN
using const_iterator = ConstIteratorSimple<char, StringView>;
public:
constexpr StringView() {}
constexpr StringView(const char* string, size_type len = -1)
StringView() {}
StringView(const String&);
StringView(const char* string, size_type len = -1)
{
if (len == size_type(-1))
len = strlen(string);
m_data = string;
m_size = len;
}
StringView(const String&);
constexpr const_iterator begin() const { return const_iterator(m_data); }
constexpr const_iterator end() const { return const_iterator(m_data + m_size); }
const_iterator begin() const { return const_iterator(m_data); }
const_iterator end() const { return const_iterator(m_data + m_size); }
constexpr char operator[](size_type index) const
char operator[](size_type index) const
{
ASSERT(index < m_size);
return m_data[index];
}
constexpr bool operator==(StringView other) const
bool operator==(StringView other) const
{
if (m_size != other.m_size)
return false;
for (size_type i = 0; i < m_size; i++)
if (m_data[i] != other.m_data[i])
return false;
return true;
return memcmp(m_data, other.m_data, m_size) == 0;
}
constexpr bool operator==(const char* other) const
bool operator==(const char* other) const
{
for (size_type i = 0; i < m_size; i++)
if (m_data[i] != other[i])
if (memcmp(m_data, other, m_size))
return false;
return other[m_size] == '\0';
}
constexpr StringView substring(size_type index, size_type len = -1) const
StringView substring(size_type index, size_type len = -1) const
{
ASSERT(index <= m_size);
if (len == size_type(-1))
@ -137,13 +133,13 @@ namespace BAN
return result;
}
constexpr char back() const
char back() const
{
ASSERT(m_size > 0);
return m_data[m_size - 1];
}
constexpr char front() const
char front() const
{
ASSERT(m_size > 0);
return m_data[0];
@ -165,7 +161,7 @@ namespace BAN
return {};
}
constexpr bool contains(char ch) const
bool contains(char ch) const
{
for (size_type i = 0; i < m_size; i++)
if (m_data[i] == ch)
@ -173,7 +169,7 @@ namespace BAN
return false;
}
constexpr size_type count(char ch) const
size_type count(char ch) const
{
size_type result = 0;
for (size_type i = 0; i < m_size; i++)
@ -182,9 +178,9 @@ namespace BAN
return result;
}
constexpr bool empty() const { return m_size == 0; }
constexpr size_type size() const { return m_size; }
constexpr const char* data() const { return m_data; }
bool empty() const { return m_size == 0; }
size_type size() const { return m_size; }
const char* data() const { return m_data; }
private:
const char* m_data = nullptr;
@ -193,7 +189,7 @@ namespace BAN
}
inline constexpr BAN::StringView operator""sv(const char* str, BAN::StringView::size_type len) { return BAN::StringView(str, len); }
inline BAN::StringView operator""sv(const char* str, BAN::StringView::size_type len) { return BAN::StringView(str, len); }
namespace BAN::Formatter
{

View File

@ -21,8 +21,6 @@ add_subdirectory(bootloader)
add_subdirectory(BAN)
add_subdirectory(libc)
add_subdirectory(LibELF)
add_subdirectory(LibGUI)
add_subdirectory(LibInput)
add_subdirectory(userspace)
add_custom_target(sysroot
@ -35,8 +33,6 @@ add_custom_target(headers
DEPENDS ban-headers
DEPENDS libc-headers
DEPENDS libelf-headers
DEPENDS libgui-headers
DEPENDS libinput-headers
)
add_custom_target(install-sysroot
@ -45,8 +41,6 @@ add_custom_target(install-sysroot
DEPENDS libc-install
DEPENDS userspace-install
DEPENDS libelf-install
DEPENDS libgui-install
DEPENDS libinput-install
)
add_custom_target(package-sysroot

View File

@ -1,24 +0,0 @@
cmake_minimum_required(VERSION 3.26)
project(libgui CXX)
set(LIBGUI_SOURCES
Window.cpp
)
add_custom_target(libgui-headers
COMMAND ${CMAKE_COMMAND} -E copy_directory_if_different ${CMAKE_CURRENT_SOURCE_DIR}/include/ ${BANAN_INCLUDE}/
DEPENDS sysroot
)
add_library(libgui ${LIBGUI_SOURCES})
add_dependencies(libgui headers libc-install)
target_link_libraries(libgui PUBLIC libc)
add_custom_target(libgui-install
COMMAND ${CMAKE_COMMAND} -E copy_if_different ${CMAKE_CURRENT_BINARY_DIR}/libgui.a ${BANAN_LIB}/
DEPENDS libgui
BYPRODUCTS ${BANAN_LIB}/libgui.a
)
set(CMAKE_STATIC_LIBRARY_PREFIX "")

View File

@ -1,115 +0,0 @@
#include "LibGUI/Window.h"
#include <fcntl.h>
#include <sys/banan-os.h>
#include <sys/mman.h>
#include <sys/select.h>
#include <sys/socket.h>
#include <sys/un.h>
#include <unistd.h>
namespace LibGUI
{
Window::~Window()
{
munmap(m_framebuffer, m_width * m_height * 4);
close(m_server_fd);
}
BAN::ErrorOr<BAN::UniqPtr<Window>> Window::create(uint32_t width, uint32_t height)
{
int server_fd = socket(AF_UNIX, SOCK_SEQPACKET, 0);
if (server_fd == -1)
return BAN::Error::from_errno(errno);
sockaddr_un server_address;
server_address.sun_family = AF_UNIX;
strcpy(server_address.sun_path, s_window_server_socket.data());
if (connect(server_fd, (sockaddr*)&server_address, sizeof(server_address)) == -1)
{
close(server_fd);
return BAN::Error::from_errno(errno);
}
WindowCreatePacket packet;
packet.width = width;
packet.height = height;
if (send(server_fd, &packet, sizeof(packet), 0) != sizeof(packet))
{
close(server_fd);
return BAN::Error::from_errno(errno);
}
WindowCreateResponse response;
if (recv(server_fd, &response, sizeof(response), 0) != sizeof(response))
{
close(server_fd);
return BAN::Error::from_errno(errno);
}
void* framebuffer_addr = smo_map(response.framebuffer_smo_key);
if (framebuffer_addr == nullptr)
{
close(server_fd);
return BAN::Error::from_errno(errno);
}
return TRY(BAN::UniqPtr<Window>::create(
server_fd,
static_cast<uint32_t*>(framebuffer_addr),
width,
height
));
}
bool Window::invalidate()
{
WindowInvalidatePacket packet;
packet.x = 0;
packet.y = 0;
packet.width = m_width;
packet.height = m_height;
return send(m_server_fd, &packet, sizeof(packet), 0) == sizeof(packet);
}
void Window::poll_events()
{
for (;;)
{
fd_set fds;
FD_ZERO(&fds);
FD_SET(m_server_fd, &fds);
timeval timeout { .tv_sec = 0, .tv_usec = 0 };
select(m_server_fd + 1, &fds, nullptr, nullptr, &timeout);
if (!FD_ISSET(m_server_fd, &fds))
break;
EventPacket packet;
if (recv(m_server_fd, &packet, sizeof(packet), 0) <= 0)
break;
switch (packet.type)
{
case EventPacket::Type::KeyEvent:
if (m_key_event_callback)
m_key_event_callback(packet.key_event);
break;
case EventPacket::Type::MouseButtonEvent:
if (m_mouse_button_event_callback)
m_mouse_button_event_callback(packet.mouse_button_event);
break;
case EventPacket::Type::MouseMoveEvent:
if (m_mouse_move_event_callback)
m_mouse_move_event_callback(packet.mouse_move_event);
break;
case EventPacket::Type::MouseScrollEvent:
if (m_mouse_scroll_event_callback)
m_mouse_scroll_event_callback(packet.mouse_scroll_event);
break;
}
}
}
}

View File

@ -1,142 +0,0 @@
#pragma once
#include <BAN/Function.h>
#include <BAN/StringView.h>
#include <BAN/UniqPtr.h>
#include <LibInput/KeyEvent.h>
#include <LibInput/MouseEvent.h>
#include <limits.h>
#include <stdint.h>
namespace LibGUI
{
static constexpr BAN::StringView s_window_server_socket = "/tmp/window-server.socket"sv;
enum WindowPacketType : uint8_t
{
INVALID,
CreateWindow,
Invalidate,
};
struct WindowCreatePacket
{
WindowPacketType type = WindowPacketType::CreateWindow;
uint32_t width;
uint32_t height;
};
struct WindowInvalidatePacket
{
WindowPacketType type = WindowPacketType::Invalidate;
uint32_t x;
uint32_t y;
uint32_t width;
uint32_t height;
};
struct WindowCreateResponse
{
long framebuffer_smo_key;
};
struct WindowPacket
{
WindowPacket()
: type(WindowPacketType::INVALID)
{ }
union
{
WindowPacketType type;
WindowCreatePacket create;
WindowInvalidatePacket invalidate;
};
};
struct EventPacket
{
enum class Type : uint8_t
{
KeyEvent,
MouseButtonEvent,
MouseMoveEvent,
MouseScrollEvent,
};
using KeyEvent = LibInput::KeyEvent;
using MouseButton = LibInput::MouseButton;
struct MouseButtonEvent
{
MouseButton button;
bool pressed;
int32_t x;
int32_t y;
};
struct MouseMoveEvent
{
int32_t x;
int32_t y;
};
using MouseScrollEvent = LibInput::MouseScrollEvent;
Type type;
union
{
KeyEvent key_event;
MouseButtonEvent mouse_button_event;
MouseMoveEvent mouse_move_event;
MouseScrollEvent mouse_scroll_event;
};
};
class Window
{
public:
~Window();
static BAN::ErrorOr<BAN::UniqPtr<Window>> create(uint32_t width, uint32_t height);
void set_pixel(uint32_t x, uint32_t y, uint32_t color)
{
ASSERT(x < m_width);
ASSERT(y < m_height);
m_framebuffer[y * m_width + x] = color;
}
bool invalidate();
uint32_t width() const { return m_width; }
uint32_t height() const { return m_height; }
void poll_events();
void set_key_event_callback(BAN::Function<void(EventPacket::KeyEvent)> callback) { m_key_event_callback = callback; }
void set_mouse_button_event_callback(BAN::Function<void(EventPacket::MouseButtonEvent)> callback) { m_mouse_button_event_callback = callback; }
void set_mouse_move_event_callback(BAN::Function<void(EventPacket::MouseMoveEvent)> callback) { m_mouse_move_event_callback = callback; }
void set_mouse_scroll_event_callback(BAN::Function<void(EventPacket::MouseScrollEvent)> callback) { m_mouse_scroll_event_callback = callback; }
private:
Window(int server_fd, uint32_t* framebuffer, uint32_t width, uint32_t height)
: m_server_fd(server_fd)
, m_framebuffer(framebuffer)
, m_width(width)
, m_height(height)
{ }
private:
int m_server_fd;
uint32_t* m_framebuffer;
uint32_t m_width;
uint32_t m_height;
BAN::Function<void(EventPacket::KeyEvent)> m_key_event_callback;
BAN::Function<void(EventPacket::MouseButtonEvent)> m_mouse_button_event_callback;
BAN::Function<void(EventPacket::MouseMoveEvent)> m_mouse_move_event_callback;
BAN::Function<void(EventPacket::MouseScrollEvent)> m_mouse_scroll_event_callback;
friend class BAN::UniqPtr<Window>;
};
}

View File

@ -1,24 +0,0 @@
cmake_minimum_required(VERSION 3.26)
project(libinput CXX)
set(LIBINPUT_SOURCES
KeyEvent.cpp
KeyboardLayout.cpp
)
add_custom_target(libinput-headers
COMMAND ${CMAKE_COMMAND} -E copy_directory_if_different ${CMAKE_CURRENT_SOURCE_DIR}/include/ ${BANAN_INCLUDE}/
DEPENDS sysroot
)
add_library(libinput ${LIBINPUT_SOURCES})
target_link_libraries(libinput PUBLIC libc ban)
add_custom_target(libinput-install
COMMAND ${CMAKE_COMMAND} -E copy_if_different ${CMAKE_CURRENT_BINARY_DIR}/libinput.a ${BANAN_LIB}/
DEPENDS libinput
BYPRODUCTS ${BANAN_LIB}/libinput.a
)
set(CMAKE_STATIC_LIBRARY_PREFIX "")

View File

@ -42,6 +42,8 @@ set(KERNEL_SOURCES
kernel/FS/VirtualFileSystem.cpp
kernel/GDT.cpp
kernel/IDT.cpp
kernel/Input/KeyboardLayout.cpp
kernel/Input/KeyEvent.cpp
kernel/Input/PS2/Controller.cpp
kernel/Input/PS2/Device.cpp
kernel/Input/PS2/Keyboard.cpp
@ -57,7 +59,6 @@ set(KERNEL_SOURCES
kernel/Memory/MemoryBackedRegion.cpp
kernel/Memory/MemoryRegion.cpp
kernel/Memory/PhysicalRange.cpp
kernel/Memory/SharedMemoryObject.cpp
kernel/Memory/VirtualRange.cpp
kernel/Networking/ARPTable.cpp
kernel/Networking/E1000/E1000.cpp
@ -149,18 +150,12 @@ set(LIBELF_SOURCES
../LibELF/LibELF/LoadableELF.cpp
)
set(LIBINPUT_SOURCE
../LibInput/KeyboardLayout.cpp
../LibInput/KeyEvent.cpp
)
set(KERNEL_SOURCES
${KERNEL_SOURCES}
${LAI_SOURCES}
${BAN_SOURCES}
${KLIBC_SOURCES}
${LIBELF_SOURCES}
${LIBINPUT_SOURCE}
)
add_executable(kernel ${KERNEL_SOURCES})

View File

@ -2,7 +2,7 @@
#include <stdint.h>
namespace LibInput
namespace Kernel::Input
{
/*
@ -53,14 +53,6 @@ namespace LibInput
Count,
};
// KeyEvent with general keycode
struct RawKeyEvent
{
uint16_t modifier;
uint8_t keycode;
};
// KeyEvent with key parsed from keycode
struct KeyEvent
{
enum Modifier : uint16_t
@ -97,9 +89,10 @@ namespace LibInput
bool released() const { return !pressed(); }
uint16_t modifier;
Key key;
uint8_t keycode;
};
Key key_event_to_key(KeyEvent);
const char* key_to_utf8(Key key, uint16_t modifier);
}

View File

@ -1,11 +1,11 @@
#pragma once
#include <BAN/Array.h>
#include <BAN/StringView.h>
#include <BAN/UniqPtr.h>
#include <LibInput/KeyEvent.h>
#include <kernel/Input/KeyEvent.h>
#include <kernel/Lock/SpinLock.h>
namespace LibInput
namespace Kernel::Input
{
class KeyboardLayout
@ -14,7 +14,7 @@ namespace LibInput
static BAN::ErrorOr<void> initialize();
static KeyboardLayout& get();
KeyEvent key_event_from_raw(RawKeyEvent);
Key get_key_from_event(KeyEvent);
BAN::ErrorOr<void> load_from_file(BAN::StringView path);
private:
@ -24,6 +24,8 @@ namespace LibInput
BAN::Array<Key, 0xFF> m_keycode_to_key_normal;
BAN::Array<Key, 0xFF> m_keycode_to_key_shift;
BAN::Array<Key, 0xFF> m_keycode_to_key_altgr;
SpinLock m_lock;
friend class BAN::UniqPtr<KeyboardLayout>;
};

View File

@ -2,7 +2,7 @@
#include <stdint.h>
namespace LibInput
namespace Kernel::Input
{
enum class MouseButton

View File

@ -2,10 +2,10 @@
#include <BAN/Array.h>
#include <BAN/CircularQueue.h>
#include <kernel/Input/KeyEvent.h>
#include <kernel/Input/PS2/Device.h>
#include <kernel/Input/PS2/Keymap.h>
#include <kernel/Semaphore.h>
#include <LibInput/KeyEvent.h>
namespace Kernel::Input
{
@ -40,7 +40,7 @@ namespace Kernel::Input
uint16_t m_modifiers { 0 };
BAN::CircularQueue<LibInput::RawKeyEvent, 50> m_event_queue;
BAN::CircularQueue<KeyEvent, 50> m_event_queue;
SpinLock m_event_lock;
PS2Keymap m_keymap;

View File

@ -1,8 +1,8 @@
#pragma once
#include <kernel/Input/MouseEvent.h>
#include <kernel/Input/PS2/Device.h>
#include <kernel/Semaphore.h>
#include <LibInput/MouseEvent.h>
namespace Kernel::Input
{
@ -36,7 +36,7 @@ namespace Kernel::Input
uint8_t m_mouse_id { 0x00 };
uint8_t m_button_mask { 0x00 };
BAN::CircularQueue<LibInput::MouseEvent, 128> m_event_queue;
BAN::CircularQueue<MouseEvent, 128> m_event_queue;
SpinLock m_event_lock;
Semaphore m_semaphore;

View File

@ -1,72 +0,0 @@
#pragma once
#include <BAN/HashMap.h>
#include <BAN/UniqPtr.h>
#include <kernel/Lock/Mutex.h>
#include <kernel/Lock/SpinLock.h>
#include <kernel/Memory/MemoryRegion.h>
namespace Kernel
{
class SharedMemoryObject;
class SharedMemoryObjectManager
{
public:
using Key = uint32_t;
public:
static BAN::ErrorOr<void> initialize();
static SharedMemoryObjectManager& get();
BAN::ErrorOr<Key> create_object(size_t size, PageTable::flags_t);
BAN::ErrorOr<BAN::UniqPtr<SharedMemoryObject>> map_object(Key, PageTable&, AddressRange);
private:
SharedMemoryObjectManager() {}
private:
struct Object : public BAN::RefCounted<Object>
{
size_t size;
PageTable::flags_t flags;
BAN::Vector<paddr_t> paddrs;
SpinLock spin_lock;
};
private:
Mutex m_mutex;
BAN::HashMap<Key, BAN::RefPtr<Object>> m_objects;
friend class SharedMemoryObject;
friend class BAN::UniqPtr<SharedMemoryObjectManager>;
};
class SharedMemoryObject : public MemoryRegion
{
BAN_NON_COPYABLE(SharedMemoryObject);
BAN_NON_MOVABLE(SharedMemoryObject);
public:
static BAN::ErrorOr<BAN::UniqPtr<SharedMemoryObject>> create(BAN::RefPtr<SharedMemoryObjectManager::Object>, PageTable&, AddressRange);
virtual BAN::ErrorOr<BAN::UniqPtr<MemoryRegion>> clone(PageTable& new_page_table) override { return BAN::Error::from_errno(ENOTSUP); }
virtual BAN::ErrorOr<void> msync(vaddr_t, size_t, int) override { return {}; }
protected:
virtual BAN::ErrorOr<bool> allocate_page_containing_impl(vaddr_t vaddr) override;
private:
SharedMemoryObject(BAN::RefPtr<SharedMemoryObjectManager::Object> object, PageTable& page_table)
: MemoryRegion(page_table, object->size, MemoryRegion::Type::SHARED, object->flags)
, m_object(object)
{ }
private:
BAN::RefPtr<SharedMemoryObjectManager::Object> m_object;
friend class BAN::UniqPtr<SharedMemoryObject>;
};
}

View File

@ -36,8 +36,6 @@ namespace Kernel
BAN::ErrorOr<off_t> seek(int fd, off_t offset, int whence);
BAN::ErrorOr<off_t> tell(int) const;
BAN::ErrorOr<void> truncate(int fd, off_t length);
BAN::ErrorOr<void> fstat(int fd, struct stat*) const;
BAN::ErrorOr<void> fstatat(int fd, BAN::StringView path, struct stat* buf, int flag);
BAN::ErrorOr<void> stat(BAN::StringView absolute_path, struct stat* buf, int flag);

View File

@ -10,7 +10,6 @@
#include <kernel/Lock/Mutex.h>
#include <kernel/Memory/Heap.h>
#include <kernel/Memory/MemoryRegion.h>
#include <kernel/Memory/SharedMemoryObject.h>
#include <kernel/OpenFileDescriptorSet.h>
#include <kernel/Terminal/TTY.h>
#include <kernel/Thread.h>
@ -139,8 +138,6 @@ namespace Kernel
BAN::ErrorOr<long> sys_seek(int fd, off_t offset, int whence);
BAN::ErrorOr<long> sys_tell(int fd);
BAN::ErrorOr<long> sys_truncate(int fd, off_t length);
BAN::ErrorOr<long> sys_fstat(int fd, struct stat*);
BAN::ErrorOr<long> sys_fstatat(int fd, const char* path, struct stat* buf, int flag);
BAN::ErrorOr<long> sys_stat(const char* path, struct stat* buf, int flag);
@ -158,9 +155,6 @@ namespace Kernel
BAN::ErrorOr<long> sys_munmap(void* addr, size_t len);
BAN::ErrorOr<long> sys_msync(void* addr, size_t len, int flags);
BAN::ErrorOr<long> sys_smo_create(size_t len, int prot);
BAN::ErrorOr<long> sys_smo_map(SharedMemoryObjectManager::Key);
BAN::ErrorOr<long> sys_tty_ctrl(int fildes, int command, int flags);
BAN::ErrorOr<long> sys_signal(int, void (*)(int));

View File

@ -11,14 +11,6 @@ namespace Kernel
static void initialize();
static uint32_t get_u32();
static uint64_t get_u64();
template<typename T>
static T get();
};
template<>
inline uint32_t Random::get<uint32_t>() { return Random::get_u32(); }
template<>
inline uint64_t Random::get<uint64_t>() { return Random::get_u64(); }
}

View File

@ -2,11 +2,11 @@
#include <BAN/Array.h>
#include <kernel/Device/Device.h>
#include <kernel/Input/KeyEvent.h>
#include <kernel/Lock/SpinLock.h>
#include <kernel/Terminal/TerminalDriver.h>
#include <kernel/Terminal/termios.h>
#include <kernel/Semaphore.h>
#include <LibInput/KeyEvent.h>
namespace Kernel
{
@ -30,7 +30,7 @@ namespace Kernel
void set_as_current();
static void initialize_devices();
void on_key_event(LibInput::KeyEvent);
void on_key_event(Input::KeyEvent);
void handle_input_byte(uint8_t);
virtual bool is_tty() const override { return true; }

View File

@ -2,6 +2,7 @@
#include <BAN/Array.h>
#include <kernel/Device/Device.h>
#include <kernel/Input/KeyEvent.h>
#include <kernel/Terminal/TerminalDriver.h>
#include <kernel/Terminal/termios.h>
#include <kernel/Terminal/TTY.h>

View File

@ -245,8 +245,6 @@ namespace Kernel
#endif
}
Debug::s_debug_lock.lock();
if (PageTable::current().get_page_flags(interrupt_stack->ip & PAGE_ADDR_MASK) & PageTable::Flags::Present)
{
auto* machine_code = (const uint8_t*)interrupt_stack->ip;
@ -295,8 +293,6 @@ namespace Kernel
PageTable::current().debug_dump();
Debug::dump_stack_trace();
Debug::s_debug_lock.unlock(InterruptState::Disabled);
if (tid && Thread::current().is_userspace())
{
// TODO: Confirm and fix the exception to signal mappings

View File

@ -1,9 +1,15 @@
#include <BAN/Array.h>
#include <LibInput/KeyEvent.h>
#include <kernel/Input/KeyboardLayout.h>
#include <kernel/Input/KeyEvent.h>
namespace LibInput
namespace Kernel::Input
{
Key key_event_to_key(KeyEvent event)
{
return KeyboardLayout::get().get_key_from_event(event);
}
const char* key_to_utf8(Key key, uint16_t modifier)
{
static constexpr const char* utf8_lower[] = {
@ -44,7 +50,7 @@ namespace LibInput
};
static_assert((size_t)Key::Count == sizeof(utf8_upper) / sizeof(*utf8_lower));
KeyEvent event { .modifier = modifier, .key = key };
KeyEvent event { .modifier = modifier, .keycode = 0x00 };
return (event.shift() ^ event.caps_lock()) ? utf8_upper[static_cast<uint8_t>(key)] : utf8_lower[static_cast<uint8_t>(key)];
}

View File

@ -1,20 +1,10 @@
#include <BAN/Debug.h>
#include <BAN/HashMap.h>
#include <BAN/String.h>
#include <BAN/StringView.h>
#include <LibInput/KeyboardLayout.h>
#if __is_kernel
#include <kernel/FS/VirtualFileSystem.h>
#else
#include <fcntl.h>
#include <limits.h>
#include <sys/stat.h>
#endif
#include <kernel/Input/KeyboardLayout.h>
#include <ctype.h>
namespace LibInput
namespace Kernel::Input
{
struct StringViewLower
@ -81,17 +71,14 @@ namespace LibInput
key = Key::None;
}
KeyEvent KeyboardLayout::key_event_from_raw(RawKeyEvent event)
Key KeyboardLayout::get_key_from_event(KeyEvent event)
{
KeyEvent result;
result.modifier = event.modifier;
if (result.shift())
result.key = m_keycode_to_key_shift[event.keycode];
else if (result.ralt())
result.key = m_keycode_to_key_altgr[event.keycode];
else
result.key = m_keycode_to_key_normal[event.keycode];
return result;
SpinLockGuard _(m_lock);
if (event.shift())
return m_keycode_to_key_shift[event.keycode];
if (event.ralt())
return m_keycode_to_key_altgr[event.keycode];
return m_keycode_to_key_normal[event.keycode];
}
static BAN::Optional<uint8_t> parse_keycode(BAN::StringView str)
@ -122,36 +109,11 @@ namespace LibInput
static BAN::ErrorOr<BAN::Vector<BAN::String>> load_keymap_lines_and_parse_includes(BAN::StringView path)
{
BAN::String file_data;
BAN::String canonical_path;
auto file = TRY(VirtualFileSystem::get().file_from_absolute_path({ 0, 0, 0, 0 }, path, 0));
#if __is_kernel
{
auto file = TRY(Kernel::VirtualFileSystem::get().file_from_absolute_path({ 0, 0, 0, 0 }, path, 0));
BAN::String file_data;
TRY(file_data.resize(file.inode->size()));
TRY(file.inode->read(0, BAN::ByteSpan { reinterpret_cast<uint8_t*>(file_data.data()), file_data.size() }));
canonical_path = file.canonical_path;
}
#else
{
char null_path[PATH_MAX];
strncpy(null_path, path.data(), path.size());
null_path[path.size()] = '\0';
struct stat st;
if (stat(null_path, &st) == -1)
return BAN::Error::from_errno(errno);
TRY(file_data.resize(st.st_size));
int fd = open(null_path, O_RDONLY);
if (fd == -1)
return BAN::Error::from_errno(errno);
ssize_t nread = read(fd, file_data.data(), st.st_size);
close(fd);
if (nread != st.st_size)
return BAN::Error::from_errno(errno);
MUST(canonical_path.append(path));
}
#endif
BAN::Vector<BAN::String> result;
@ -180,7 +142,7 @@ namespace LibInput
parts[1] = parts[1].substring(1, parts[1].size() - 2);
BAN::String include_path;
TRY(include_path.append(canonical_path));
TRY(include_path.append(file.canonical_path));
ASSERT(include_path.sv().contains('/'));
while (include_path.back() != '/')
include_path.pop_back();
@ -294,6 +256,8 @@ namespace LibInput
}
}
SpinLockGuard _(m_lock);
for (size_t i = 0; i < new_layout->m_keycode_to_key_normal.size(); i++)
if (new_layout->m_keycode_to_key_normal[i] != Key::None)
m_keycode_to_key_normal[i] = new_layout->m_keycode_to_key_normal[i];

View File

@ -1,9 +1,9 @@
#include <BAN/ScopeGuard.h>
#include <kernel/FS/DevFS/FileSystem.h>
#include <kernel/Input/KeyboardLayout.h>
#include <kernel/Input/PS2/Config.h>
#include <kernel/Input/PS2/Keyboard.h>
#include <kernel/Thread.h>
#include <LibInput/KeyboardLayout.h>
namespace Kernel::Input
{
@ -44,10 +44,6 @@ namespace Kernel::Input
void PS2Keyboard::handle_byte(uint8_t byte)
{
using LibInput::Key;
using LibInput::RawKeyEvent;
using KeyModifier = LibInput::KeyEvent::Modifier;
if (byte == PS2::KBResponse::KEY_ERROR_OR_BUFFER_OVERRUN1 || byte == PS2::KBResponse::KEY_ERROR_OR_BUFFER_OVERRUN2)
{
dwarnln("Key detection error or internal buffer overrun");
@ -127,24 +123,25 @@ namespace Kernel::Input
if (!keycode.has_value())
return;
auto dummy_event = LibInput::KeyboardLayout::get().key_event_from_raw(RawKeyEvent { .modifier = 0, .keycode = keycode.value() });
if (dummy_event.key == Key::F1)
auto key = KeyboardLayout::get().get_key_from_event(KeyEvent { .modifier = 0, .keycode = keycode.value() });
if (key == Key::F1)
panic("OOF");
uint16_t modifier_mask = 0;
uint16_t toggle_mask = 0;
switch (dummy_event.key)
switch (key)
{
case Key::LeftShift: modifier_mask = KeyModifier::LShift; break;
case Key::RightShift: modifier_mask = KeyModifier::RShift; break;
case Key::LeftCtrl: modifier_mask = KeyModifier::LCtrl; break;
case Key::RightCtrl: modifier_mask = KeyModifier::RCtrl; break;
case Key::LeftAlt: modifier_mask = KeyModifier::LAlt; break;
case Key::RightAlt: modifier_mask = KeyModifier::RAlt; break;
case Key::LeftShift: modifier_mask = KeyEvent::Modifier::LShift; break;
case Key::RightShift: modifier_mask = KeyEvent::Modifier::RShift; break;
case Key::LeftCtrl: modifier_mask = KeyEvent::Modifier::LCtrl; break;
case Key::RightCtrl: modifier_mask = KeyEvent::Modifier::RCtrl; break;
case Key::LeftAlt: modifier_mask = KeyEvent::Modifier::LAlt; break;
case Key::RightAlt: modifier_mask = KeyEvent::Modifier::RAlt; break;
case Key::ScrollLock: toggle_mask = KeyModifier::ScrollLock; break;
case Key::NumLock: toggle_mask = KeyModifier::NumLock; break;
case Key::CapsLock: toggle_mask = KeyModifier::CapsLock; break;
case Key::ScrollLock: toggle_mask = KeyEvent::Modifier::ScrollLock; break;
case Key::NumLock: toggle_mask = KeyEvent::Modifier::NumLock; break;
case Key::CapsLock: toggle_mask = KeyEvent::Modifier::CapsLock; break;
default: break;
}
@ -163,8 +160,8 @@ namespace Kernel::Input
update_leds();
}
RawKeyEvent event;
event.modifier = m_modifiers | (released ? 0 : KeyModifier::Pressed);
KeyEvent event;
event.modifier = m_modifiers | (released ? 0 : KeyEvent::Modifier::Pressed);
event.keycode = keycode.value();
SpinLockGuard _(m_event_lock);
@ -181,23 +178,19 @@ namespace Kernel::Input
void PS2Keyboard::update_leds()
{
using KeyModifier = LibInput::KeyEvent::Modifier;
uint8_t new_leds = 0;
if (m_modifiers & +KeyModifier::ScrollLock)
if (m_modifiers & +KeyEvent::Modifier::ScrollLock)
new_leds |= PS2::KBLeds::SCROLL_LOCK;
if (m_modifiers & +KeyModifier::NumLock)
if (m_modifiers & +KeyEvent::Modifier::NumLock)
new_leds |= PS2::KBLeds::NUM_LOCK;
if (m_modifiers & +KeyModifier::CapsLock)
if (m_modifiers & +KeyEvent::Modifier::CapsLock)
new_leds |= PS2::KBLeds::CAPS_LOCK;
append_command_queue(Command::SET_LEDS, new_leds, 0);
}
BAN::ErrorOr<size_t> PS2Keyboard::read_impl(off_t, BAN::ByteSpan buffer)
{
using LibInput::RawKeyEvent;
if (buffer.size() < sizeof(RawKeyEvent))
if (buffer.size() < sizeof(KeyEvent))
return BAN::Error::from_errno(ENOBUFS);
auto state = m_event_lock.lock();
@ -208,12 +201,12 @@ namespace Kernel::Input
state = m_event_lock.lock();
}
buffer.as<RawKeyEvent>() = m_event_queue.front();
buffer.as<KeyEvent>() = m_event_queue.front();
m_event_queue.pop();
m_event_lock.unlock(state);
return sizeof(RawKeyEvent);
return sizeof(KeyEvent);
}
}

View File

@ -1,14 +1,11 @@
#include <kernel/Debug.h>
#include <kernel/Input/KeyEvent.h>
#include <kernel/Input/PS2/Keymap.h>
#include <LibInput/KeyEvent.h>
#include <string.h>
namespace Kernel::Input
{
using LibInput::keycode_function;
using LibInput::keycode_normal;
using LibInput::keycode_numpad;
void PS2Keymap::initialize(uint8_t scancode_set)
{

View File

@ -71,10 +71,6 @@ namespace Kernel::Input
void PS2Mouse::handle_byte(uint8_t byte)
{
using LibInput::MouseButton;
using LibInput::MouseEvent;
using LibInput::MouseEventType;
if (!m_enabled)
return initialize_extensions(byte);
@ -178,8 +174,6 @@ namespace Kernel::Input
BAN::ErrorOr<size_t> PS2Mouse::read_impl(off_t, BAN::ByteSpan buffer)
{
using LibInput::MouseEvent;
if (buffer.size() < sizeof(MouseEvent))
return BAN::Error::from_errno(ENOBUFS);

View File

@ -1,88 +0,0 @@
#include <kernel/Lock/LockGuard.h>
#include <kernel/Memory/Heap.h>
#include <kernel/Memory/SharedMemoryObject.h>
#include <kernel/Random.h>
namespace Kernel
{
static BAN::UniqPtr<SharedMemoryObjectManager> s_instance;
BAN::ErrorOr<void> SharedMemoryObjectManager::initialize()
{
ASSERT(!s_instance);
s_instance = TRY(BAN::UniqPtr<SharedMemoryObjectManager>::create());
return {};
}
SharedMemoryObjectManager& SharedMemoryObjectManager::get()
{
ASSERT(s_instance);
return *s_instance;
}
BAN::ErrorOr<SharedMemoryObjectManager::Key> SharedMemoryObjectManager::create_object(size_t size, PageTable::flags_t flags)
{
ASSERT(size % PAGE_SIZE == 0);
auto object = TRY(BAN::RefPtr<Object>::create());
object->size = size;
object->flags = flags;
TRY(object->paddrs.resize(size / PAGE_SIZE, 0));
LockGuard _(m_mutex);
Key key = Random::get<Key>();
while (m_objects.contains(key))
key = Random::get<Key>();
TRY(m_objects.insert(key, object));
return key;
}
BAN::ErrorOr<BAN::UniqPtr<SharedMemoryObject>> SharedMemoryObjectManager::map_object(Key key, PageTable& page_table, AddressRange address_range)
{
LockGuard _(m_mutex);
auto it = m_objects.find(key);
if (it == m_objects.end())
return BAN::Error::from_errno(ENOENT);
return TRY(SharedMemoryObject::create(it->value, page_table, address_range));
}
BAN::ErrorOr<BAN::UniqPtr<SharedMemoryObject>> SharedMemoryObject::create(BAN::RefPtr<SharedMemoryObjectManager::Object> object, PageTable& page_table, AddressRange address_range)
{
auto smo = TRY(BAN::UniqPtr<SharedMemoryObject>::create(object, page_table));
TRY(smo->initialize(address_range));
return BAN::move(smo);
}
BAN::ErrorOr<bool> SharedMemoryObject::allocate_page_containing_impl(vaddr_t address)
{
ASSERT(contains(address));
// Check if address is already mapped
vaddr_t vaddr = address & PAGE_ADDR_MASK;
if (m_page_table.physical_address_of(vaddr) != 0)
return false;
SpinLockGuard _(m_object->spin_lock);
paddr_t paddr = m_object->paddrs[(vaddr - m_vaddr) / PAGE_SIZE];
if (paddr == 0)
{
paddr = Heap::get().take_free_page();
if (paddr == 0)
return BAN::Error::from_errno(ENOMEM);
PageTable::with_fast_page(paddr, [&] {
memset(PageTable::fast_page_as_ptr(), 0x00, PAGE_SIZE);
});
m_object->paddrs[(vaddr - m_vaddr) / PAGE_SIZE] = paddr;
}
m_page_table.map_page_at(paddr, vaddr, m_flags);
return true;
}
}

View File

@ -242,12 +242,6 @@ namespace Kernel
return m_open_files[fd]->offset;
}
BAN::ErrorOr<void> OpenFileDescriptorSet::truncate(int fd, off_t length)
{
TRY(validate_fd(fd));
return m_open_files[fd]->inode->truncate(length);
}
static void read_stat_from_inode(BAN::RefPtr<Inode> inode, struct stat* out)
{
out->st_dev = inode->dev();

View File

@ -5,6 +5,7 @@
#include <kernel/FS/ProcFS/FileSystem.h>
#include <kernel/FS/VirtualFileSystem.h>
#include <kernel/IDT.h>
#include <kernel/Input/KeyboardLayout.h>
#include <kernel/InterruptController.h>
#include <kernel/Lock/LockGuard.h>
#include <kernel/Memory/FileBackedRegion.h>
@ -16,7 +17,6 @@
#include <kernel/Timer/Timer.h>
#include <LibELF/LoadableELF.h>
#include <LibInput/KeyboardLayout.h>
#include <fcntl.h>
#include <stdio.h>
@ -1045,6 +1045,9 @@ namespace Kernel
int set_bits = 0;
for (;;)
{
if (arguments->timeout && SystemTimer::get().ms_since_boot() >= timedout_ms)
break;
auto update_fds =
[&](int fd, fd_set* source, fd_set* dest, bool (Inode::*func)() const)
{
@ -1059,6 +1062,10 @@ namespace Kernel
return;
auto inode = inode_or_error.release_value();
auto mode = inode->mode();
if (!mode.ifreg() && !mode.ififo() && !mode.ifsock() && !inode->is_pipe() && !inode->is_tty())
return;
if ((inode.ptr()->*func)())
{
FD_SET(fd, dest);
@ -1076,9 +1083,6 @@ namespace Kernel
if (set_bits > 0)
break;
if (arguments->timeout && SystemTimer::get().ms_since_boot() >= timedout_ms)
break;
LockFreeGuard free(m_process_lock);
SystemTimer::get().sleep(1);
}
@ -1141,13 +1145,6 @@ namespace Kernel
return TRY(m_open_file_descriptors.tell(fd));
}
BAN::ErrorOr<long> Process::sys_truncate(int fd, off_t length)
{
LockGuard _(m_process_lock);
TRY(m_open_file_descriptors.truncate(fd, length));
return 0;
}
BAN::ErrorOr<void> Process::mount(BAN::StringView source, BAN::StringView target)
{
BAN::String absolute_source, absolute_target;
@ -1392,41 +1389,6 @@ namespace Kernel
return 0;
}
BAN::ErrorOr<long> Process::sys_smo_create(size_t len, int prot)
{
if (len == 0)
return BAN::Error::from_errno(EINVAL);
if (prot & ~(PROT_READ | PROT_WRITE | PROT_EXEC | PROT_NONE))
return BAN::Error::from_errno(EINVAL);
if (auto rem = len % PAGE_SIZE)
len += PAGE_SIZE - rem;
PageTable::flags_t page_flags = 0;
if (prot & PROT_READ)
page_flags |= PageTable::Flags::Present;
if (prot & PROT_WRITE)
page_flags |= PageTable::Flags::ReadWrite | PageTable::Flags::Present;
if (prot & PROT_EXEC)
page_flags |= PageTable::Flags::Execute | PageTable::Flags::Present;
if (page_flags == 0)
page_flags |= PageTable::Flags::Reserved;
else
page_flags |= PageTable::Flags::UserSupervisor;
return TRY(SharedMemoryObjectManager::get().create_object(len, page_flags));
}
BAN::ErrorOr<long> Process::sys_smo_map(SharedMemoryObjectManager::Key key)
{
auto region = TRY(SharedMemoryObjectManager::get().map_object(key, page_table(), { .start = 0x400000, .end = KERNEL_OFFSET }));
LockGuard _(m_process_lock);
TRY(m_mapped_regions.push_back(BAN::move(region)));
return m_mapped_regions.back()->vaddr();
}
BAN::ErrorOr<long> Process::sys_tty_ctrl(int fildes, int command, int flags)
{
LockGuard _(m_process_lock);
@ -1495,7 +1457,7 @@ namespace Kernel
return BAN::Error::from_errno(EPERM);
auto absolute_path = TRY(absolute_path_of(path));
TRY(LibInput::KeyboardLayout::get().load_from_file(absolute_path));
TRY(Input::KeyboardLayout::get().load_from_file(absolute_path));
return 0;
}

View File

@ -7,7 +7,6 @@
#include <kernel/Lock/LockGuard.h>
#include <kernel/Process.h>
#include <kernel/Terminal/TTY.h>
#include <LibInput/KeyboardLayout.h>
#include <fcntl.h>
#include <string.h>
@ -95,11 +94,10 @@ namespace Kernel
while (!TTY::current()->m_tty_ctrl.receive_input)
TTY::current()->m_tty_ctrl.semaphore.block_indefinite();
LibInput::RawKeyEvent event;
Input::KeyEvent event;
size_t read = MUST(inode->read(0, BAN::ByteSpan::from(event)));
ASSERT(read == sizeof(event));
TTY::current()->on_key_event(LibInput::KeyboardLayout::get().key_event_from_raw(event));
TTY::current()->on_key_event(event);
}
}, nullptr
);
@ -122,70 +120,71 @@ namespace Kernel
return {};
}
void TTY::on_key_event(LibInput::KeyEvent event)
void TTY::on_key_event(Input::KeyEvent event)
{
LockGuard _(m_mutex);
if (event.released())
return;
const char* ansi_c_str = LibInput::key_to_utf8(event.key, event.modifier);
Input::Key key = Input::key_event_to_key(event);
const char* ansi_c_str = Input::key_to_utf8(key, event.modifier);
if (event.ctrl())
{
ansi_c_str = nullptr;
switch (event.key)
switch (key)
{
case LibInput::Key::A: ansi_c_str = "\x01"; break;
case LibInput::Key::B: ansi_c_str = "\x02"; break;
case LibInput::Key::C: ansi_c_str = "\x03"; break;
case LibInput::Key::D: ansi_c_str = "\x04"; break;
case LibInput::Key::E: ansi_c_str = "\x05"; break;
case LibInput::Key::F: ansi_c_str = "\x06"; break;
case LibInput::Key::G: ansi_c_str = "\x07"; break;
case LibInput::Key::H: ansi_c_str = "\x08"; break;
case LibInput::Key::I: ansi_c_str = "\x09"; break;
case LibInput::Key::J: ansi_c_str = "\x0A"; break;
case LibInput::Key::K: ansi_c_str = "\x0B"; break;
case LibInput::Key::L: ansi_c_str = "\x0C"; break;
case LibInput::Key::M: ansi_c_str = "\x0D"; break;
case LibInput::Key::N: ansi_c_str = "\x0E"; break;
case LibInput::Key::O: ansi_c_str = "\x0F"; break;
case LibInput::Key::P: ansi_c_str = "\x10"; break;
case LibInput::Key::Q: ansi_c_str = "\x11"; break;
case LibInput::Key::R: ansi_c_str = "\x12"; break;
case LibInput::Key::S: ansi_c_str = "\x13"; break;
case LibInput::Key::T: ansi_c_str = "\x14"; break;
case LibInput::Key::U: ansi_c_str = "\x15"; break;
case LibInput::Key::V: ansi_c_str = "\x16"; break;
case LibInput::Key::W: ansi_c_str = "\x17"; break;
case LibInput::Key::X: ansi_c_str = "\x18"; break;
case LibInput::Key::Y: ansi_c_str = "\x19"; break;
case LibInput::Key::Z: ansi_c_str = "\x1A"; break;
case Input::Key::A: ansi_c_str = "\x01"; break;
case Input::Key::B: ansi_c_str = "\x02"; break;
case Input::Key::C: ansi_c_str = "\x03"; break;
case Input::Key::D: ansi_c_str = "\x04"; break;
case Input::Key::E: ansi_c_str = "\x05"; break;
case Input::Key::F: ansi_c_str = "\x06"; break;
case Input::Key::G: ansi_c_str = "\x07"; break;
case Input::Key::H: ansi_c_str = "\x08"; break;
case Input::Key::I: ansi_c_str = "\x09"; break;
case Input::Key::J: ansi_c_str = "\x0A"; break;
case Input::Key::K: ansi_c_str = "\x0B"; break;
case Input::Key::L: ansi_c_str = "\x0C"; break;
case Input::Key::M: ansi_c_str = "\x0D"; break;
case Input::Key::N: ansi_c_str = "\x0E"; break;
case Input::Key::O: ansi_c_str = "\x0F"; break;
case Input::Key::P: ansi_c_str = "\x10"; break;
case Input::Key::Q: ansi_c_str = "\x11"; break;
case Input::Key::R: ansi_c_str = "\x12"; break;
case Input::Key::S: ansi_c_str = "\x13"; break;
case Input::Key::T: ansi_c_str = "\x14"; break;
case Input::Key::U: ansi_c_str = "\x15"; break;
case Input::Key::V: ansi_c_str = "\x16"; break;
case Input::Key::W: ansi_c_str = "\x17"; break;
case Input::Key::X: ansi_c_str = "\x18"; break;
case Input::Key::Y: ansi_c_str = "\x19"; break;
case Input::Key::Z: ansi_c_str = "\x1A"; break;
default: break;
}
}
else
{
switch (event.key)
switch (key)
{
case LibInput::Key::Enter:
case LibInput::Key::NumpadEnter:
case Input::Key::Enter:
case Input::Key::NumpadEnter:
ansi_c_str = "\n";
break;
case LibInput::Key::Backspace:
case Input::Key::Backspace:
ansi_c_str = "\b";
break;
case LibInput::Key::ArrowUp:
case Input::Key::ArrowUp:
ansi_c_str = "\e[A";
break;
case LibInput::Key::ArrowDown:
case Input::Key::ArrowDown:
ansi_c_str = "\e[B";
break;
case LibInput::Key::ArrowRight:
case Input::Key::ArrowRight:
ansi_c_str = "\e[C";
break;
case LibInput::Key::ArrowLeft:
case Input::Key::ArrowLeft:
ansi_c_str = "\e[D";
break;
default:

View File

@ -75,9 +75,8 @@ namespace Kernel
return;
uint64_t wake_time = ms_since_boot() + ms;
Scheduler::get().set_current_thread_sleeping(wake_time);
uint64_t current_time = ms_since_boot();
if (current_time < wake_time)
dwarnln("sleep woke {} ms too soon", wake_time - current_time);
if (ms_since_boot() < wake_time)
dwarnln("sleep woke {} ms too soon", wake_time - ms_since_boot());
}
timespec SystemTimer::real_time() const

View File

@ -8,13 +8,13 @@
#include <kernel/FS/VirtualFileSystem.h>
#include <kernel/GDT.h>
#include <kernel/IDT.h>
#include <kernel/Input/KeyboardLayout.h>
#include <kernel/Input/PS2/Controller.h>
#include <kernel/InterruptController.h>
#include <kernel/kprint.h>
#include <kernel/Memory/Heap.h>
#include <kernel/Memory/kmalloc.h>
#include <kernel/Memory/PageTable.h>
#include <kernel/Memory/SharedMemoryObject.h>
#include <kernel/Networking/NetworkManager.h>
#include <kernel/PCI.h>
#include <kernel/PIC.h>
@ -28,8 +28,6 @@
#include <kernel/Terminal/VirtualTTY.h>
#include <kernel/Timer/Timer.h>
#include <LibInput/KeyboardLayout.h>
struct ParsedCommandLine
{
bool force_pic = false;
@ -144,9 +142,6 @@ extern "C" void kernel_main(uint32_t boot_magic, uint32_t boot_info)
ProcFileSystem::initialize();
dprintln("procfs initialized");
MUST(SharedMemoryObjectManager::initialize());
dprintln("Shared memory object system initialized");
if (Serial::has_devices())
{
Serial::initialize_devices();
@ -199,7 +194,7 @@ static void init2(void*)
#endif
// Initialize empty keymap
MUST(LibInput::KeyboardLayout::initialize());
MUST(Input::KeyboardLayout::initialize());
if (auto res = PS2Controller::initialize(); res.is_error())
dprintln("{}", res.error());

View File

@ -59,7 +59,6 @@ __BEGIN_DECLS
#define OPEN_MAX 64
#define NAME_MAX 255
#define PATH_MAX 256
#define LOGIN_NAME_MAX 256
__END_DECLS

View File

@ -36,11 +36,6 @@ int poweroff(int command);
int load_keymap(const char* path);
// Create shared memory object and return its key or -1 on error
long smo_create(size_t size, int prot);
// Map shared memory object defined by its key and return address or null on error
void* smo_map(long key);
__END_DECLS
#endif

View File

@ -73,9 +73,6 @@ __BEGIN_DECLS
O(SYS_CONNECT, connect) \
O(SYS_LISTEN, listen) \
O(SYS_PSELECT, pselect) \
O(SYS_TRUNCATE, truncate) \
O(SYS_SMO_CREATE, smo_create) \
O(SYS_SMO_MAP, smo_map) \
enum Syscall
{

View File

@ -16,16 +16,3 @@ int load_keymap(const char* path)
{
return syscall(SYS_LOAD_KEYMAP, path);
}
long smo_create(size_t size, int prot)
{
return syscall(SYS_SMO_CREATE, size, prot);
}
void* smo_map(long key)
{
long ret = syscall(SYS_SMO_MAP, key);
if (ret < 0)
return nullptr;
return reinterpret_cast<void*>(ret);
}

View File

@ -99,11 +99,6 @@ off_t lseek(int fildes, off_t offset, int whence)
return syscall(SYS_SEEK, fildes, offset, whence);
}
int ftruncate(int fildes, off_t length)
{
return syscall(SYS_TRUNCATE, fildes, length);
}
int dup(int fildes)
{
return syscall(SYS_DUP, fildes);

View File

@ -39,11 +39,9 @@ set(USERSPACE_PROJECTS
test-tcp
test-udp
test-unix-socket
test-window
touch
u8sum
whoami
WindowServer
yes
)

View File

@ -1,18 +0,0 @@
cmake_minimum_required(VERSION 3.26)
project(WindowServer CXX)
set(SOURCES
main.cpp
Framebuffer.cpp
WindowServer.cpp
)
add_executable(WindowServer ${SOURCES})
target_compile_options(WindowServer PUBLIC -O2 -g)
target_link_libraries(WindowServer PUBLIC libc ban libgui libinput)
add_custom_target(WindowServer-install
COMMAND ${CMAKE_COMMAND} -E copy ${CMAKE_CURRENT_BINARY_DIR}/WindowServer ${BANAN_BIN}/
DEPENDS WindowServer
)

View File

@ -1,35 +0,0 @@
/* GIMP header image file format (RGB) */
#include <stdint.h>
static int32_t s_cursor_width = 17;
static int32_t s_cursor_height = 26;
static const char* s_cursor_data =
"!!!!`Q$``Q$``Q$``Q$``Q$``Q$``Q$``Q$``Q$``Q$``Q$``Q$``Q$``Q$``Q$`"
"`Q$`!!!!!!!!`Q$``Q$``Q$``Q$``Q$``Q$``Q$``Q$``Q$``Q$``Q$``Q$``Q$`"
"`Q$``Q$`!!!!````!!!!`Q$``Q$``Q$``Q$``Q$``Q$``Q$``Q$``Q$``Q$``Q$`"
"`Q$``Q$``Q$`!!!!````````!!!!`Q$``Q$``Q$``Q$``Q$``Q$``Q$``Q$``Q$`"
"`Q$``Q$``Q$``Q$`!!!!````````````!!!!`Q$``Q$``Q$``Q$``Q$``Q$``Q$`"
"`Q$``Q$``Q$``Q$``Q$`!!!!````````````````!!!!`Q$``Q$``Q$``Q$``Q$`"
"`Q$``Q$``Q$``Q$``Q$``Q$`!!!!````````````````````!!!!`Q$``Q$``Q$`"
"`Q$``Q$``Q$``Q$``Q$``Q$``Q$`!!!!````````````````````````!!!!`Q$`"
"`Q$``Q$``Q$``Q$``Q$``Q$``Q$``Q$`!!!!````````````````````````````"
"!!!!`Q$``Q$``Q$``Q$``Q$``Q$``Q$``Q$`!!!!````````````````````````"
"````````!!!!`Q$``Q$``Q$``Q$``Q$``Q$``Q$`!!!!````````````````````"
"````````````````!!!!`Q$``Q$``Q$``Q$``Q$``Q$`!!!!````````````````"
"````````````````````````!!!!`Q$``Q$``Q$``Q$``Q$`!!!!````````````"
"````````````````````````````````!!!!`Q$``Q$``Q$``Q$`!!!!````````"
"````````````````````````````````````````!!!!`Q$``Q$``Q$`!!!!````"
"````````````````````````````````````````````````!!!!`Q$``Q$`!!!!"
"````````````````````````````````````````````````````````!!!!`Q$`"
"!!!!````````````````````````````````!!!!!!!!!!!!!!!!!!!!!!!!!!!!"
"!!!!!!!!````````````````````````````````!!!!`Q$``Q$``Q$``Q$``Q$`"
"`Q$``Q$`!!!!````````````````!!!!````````````````!!!!`Q$``Q$``Q$`"
"`Q$``Q$``Q$`!!!!````````````!!!!`Q$`!!!!````````````!!!!`Q$``Q$`"
"`Q$``Q$``Q$``Q$`!!!!````````!!!!`Q$``Q$`!!!!````````````````!!!!"
"`Q$``Q$``Q$``Q$``Q$`!!!!````!!!!`Q$``Q$``Q$``Q$`!!!!````````````"
"!!!!`Q$``Q$``Q$``Q$``Q$`!!!!!!!!`Q$``Q$``Q$``Q$``Q$`!!!!````````"
"````````!!!!`Q$``Q$``Q$``Q$`!!!!`Q$``Q$``Q$``Q$``Q$``Q$``Q$`!!!!"
"````````````!!!!`Q$``Q$``Q$``Q$``Q$``Q$``Q$``Q$``Q$``Q$``Q$``Q$`"
"!!!!````````````!!!!`Q$``Q$``Q$``Q$``Q$``Q$``Q$``Q$``Q$``Q$``Q$`"
"`Q$``Q$`!!!!!!!!!!!!`Q$``Q$``Q$``Q$``Q$`";

View File

@ -1,45 +0,0 @@
#include "Framebuffer.h"
#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/framebuffer.h>
#include <sys/mman.h>
Framebuffer open_framebuffer()
{
int framebuffer_fd = open("/dev/fb0", O_RDWR);
if (framebuffer_fd == -1)
{
perror("open");
exit(1);
}
framebuffer_info_t framebuffer_info;
if (pread(framebuffer_fd, &framebuffer_info, sizeof(framebuffer_info), -1) == -1)
{
perror("pread");
exit(1);
}
const size_t framebuffer_bytes = framebuffer_info.width * framebuffer_info.height * (BANAN_FB_BPP / 8);
uint32_t* framebuffer_mmap = (uint32_t*)mmap(NULL, framebuffer_bytes, PROT_READ | PROT_WRITE, MAP_SHARED, framebuffer_fd, 0);
if (framebuffer_mmap == MAP_FAILED)
{
perror("mmap");
exit(1);
}
memset(framebuffer_mmap, 0, framebuffer_bytes);
msync(framebuffer_mmap, framebuffer_bytes, MS_SYNC);
Framebuffer framebuffer;
framebuffer.fd = framebuffer_fd;
framebuffer.mmap = framebuffer_mmap;
framebuffer.width = framebuffer_info.width;
framebuffer.height = framebuffer_info.height;
framebuffer.bpp = BANAN_FB_BPP;
return framebuffer;
}

View File

@ -1,16 +0,0 @@
#pragma once
#include "Utils.h"
struct Framebuffer
{
int fd;
uint32_t* mmap;
int32_t width;
int32_t height;
uint8_t bpp;
Rectangle area() const { return { 0, 0, width, height }; }
};
Framebuffer open_framebuffer();

View File

@ -1,59 +0,0 @@
#pragma once
#include <BAN/Math.h>
#include <BAN/Optional.h>
#include <stdint.h>
struct Position
{
int32_t x;
int32_t y;
};
struct Rectangle
{
int32_t x;
int32_t y;
int32_t width;
int32_t height;
bool contains(Position position) const
{
if (position.x < x || position.x >= x + width)
return false;
if (position.y < y || position.y >= y + height)
return false;
return true;
}
BAN::Optional<Rectangle> get_overlap(Rectangle other) const
{
const auto min_x = BAN::Math::max(x, other.x);
const auto min_y = BAN::Math::max(y, other.y);
const auto max_x = BAN::Math::min(x + width, other.x + other.width);
const auto max_y = BAN::Math::min(y + height, other.y + other.height);
if (min_x >= max_x || min_y >= max_y)
return {};
return Rectangle {
.x = min_x,
.y = min_y,
.width = max_x - min_x,
.height = max_y - min_y,
};
}
Rectangle get_bounding_box(Rectangle other) const
{
const auto min_x = BAN::Math::min(x, other.x);
const auto min_y = BAN::Math::min(y, other.y);
const auto max_x = BAN::Math::max(x + width, other.x + other.width);
const auto max_y = BAN::Math::max(y + height, other.y + other.height);
return Rectangle {
.x = min_x,
.y = min_y,
.width = max_x - min_x,
.height = max_y - min_y,
};
}
};

View File

@ -1,45 +0,0 @@
#pragma once
#include "Utils.h"
#include <BAN/RefPtr.h>
class Window : public BAN::RefCounted<Window>
{
public:
Window(int fd)
: m_client_fd(fd)
{ }
void set_position(Position position)
{
m_area.x = position.x;
m_area.y = position.y;
}
void set_size(Position size, uint32_t* fb_addr)
{
m_area.width = size.x;
m_area.height = size.y;
m_fb_addr = fb_addr;
}
bool is_deleted() const { return m_deleted; }
void mark_deleted() { m_deleted = true; }
int client_fd() const { return m_client_fd; }
int32_t x() const { return m_area.x; }
int32_t y() const { return m_area.y; }
uint32_t width() const { return m_area.width; }
uint32_t height() const { return m_area.height; }
Rectangle size() const { return { 0, 0, m_area.width, m_area.height }; }
const Rectangle& area() const { return m_area; }
const uint32_t* framebuffer() const { return m_fb_addr; }
private:
const int m_client_fd { -1 };
uint32_t* m_fb_addr { nullptr };
Rectangle m_area { 0, 0, 0, 0 };
bool m_deleted { false };
};

View File

@ -1,224 +0,0 @@
#include "Cursor.h"
#include "WindowServer.h"
#include <LibGUI/Window.h>
#include <LibInput/KeyboardLayout.h>
#include <stdlib.h>
#include <sys/mman.h>
#include <sys/socket.h>
void WindowServer::add_window(int fd, BAN::RefPtr<Window> window)
{
MUST(m_windows_ordered.insert(0, window));
MUST(m_windows.insert(fd, window));
set_focused_window(window);
}
void WindowServer::for_each_window(const BAN::Function<BAN::Iteration(int, Window&)>& callback)
{
BAN::Vector<int> deleted_windows;
for (auto it = m_windows.begin(); it != m_windows.end(); it++)
{
auto ret = callback(it->key, *it->value);
if (it->value->is_deleted())
MUST(deleted_windows.push_back(it->key));
if (ret == BAN::Iteration::Break)
break;
ASSERT(ret == BAN::Iteration::Continue);
}
for (int fd : deleted_windows)
{
auto window = m_windows[fd];
m_windows.remove(fd);
for (size_t i = 0; i < m_windows_ordered.size(); i++)
{
if (m_windows_ordered[i] == window)
{
m_windows_ordered.remove(i);
break;
}
}
}
}
void WindowServer::on_key_event(LibInput::KeyEvent event)
{
// Mod key is not passed to clients
if (event.key == LibInput::Key::Super)
{
m_is_mod_key_held = event.pressed();
return;
}
// Quick hack to stop the window server
if (event.pressed() && event.key == LibInput::Key::Escape)
exit(0);
if (m_focused_window)
{
LibGUI::EventPacket packet;
packet.type = LibGUI::EventPacket::Type::KeyEvent;
packet.key_event = event;
send(m_focused_window->client_fd(), &packet, sizeof(packet), 0);
}
}
void WindowServer::on_mouse_button(LibInput::MouseButtonEvent event)
{
BAN::RefPtr<Window> target_window;
for (size_t i = m_windows_ordered.size(); i > 0; i--)
{
if (m_windows_ordered[i - 1]->area().contains(m_cursor))
{
target_window = m_windows_ordered[i - 1];
break;
}
}
// Ignore mouse button events which are not on top of a window
if (!target_window)
return;
set_focused_window(target_window);
// Handle window moving when mod key is held
if (m_is_mod_key_held && event.pressed && event.button == LibInput::MouseButton::Left && !m_is_moving_window)
m_is_moving_window = true;
else if (m_is_moving_window && !event.pressed)
m_is_moving_window = false;
else
{
// NOTE: we always have target window if code reaches here
LibGUI::EventPacket packet;
packet.type = LibGUI::EventPacket::Type::MouseButtonEvent;
packet.mouse_button_event.button = event.button;
packet.mouse_button_event.pressed = event.pressed;
packet.mouse_button_event.x = m_cursor.x - m_focused_window->x();
packet.mouse_button_event.y = m_cursor.y - m_focused_window->y();
send(m_focused_window->client_fd(), &packet, sizeof(packet), 0);
}
}
void WindowServer::on_mouse_move(LibInput::MouseMoveEvent event)
{
Rectangle old_cursor { m_cursor.x, m_cursor.y, s_cursor_width, s_cursor_height };
const int32_t new_x = BAN::Math::clamp(m_cursor.x + event.rel_x, 0, m_framebuffer.width);
const int32_t new_y = BAN::Math::clamp(m_cursor.y - event.rel_y, 0, m_framebuffer.height);
event.rel_x = new_x - m_cursor.x;
event.rel_y = new_y - m_cursor.y;
if (event.rel_x == 0 && event.rel_y == 0)
return;
m_cursor.x = new_x;
m_cursor.y = new_y;
Rectangle new_cursor { m_cursor.x, m_cursor.y, s_cursor_width, s_cursor_height };
invalidate(old_cursor.get_bounding_box(old_cursor));
invalidate(new_cursor.get_bounding_box(old_cursor));
if (m_is_moving_window)
{
auto old_window = m_focused_window->area();
m_focused_window->set_position({
m_focused_window->x() + event.rel_x,
m_focused_window->y() + event.rel_y,
});
invalidate(old_window);
invalidate(m_focused_window->area());
return;
}
if (m_focused_window)
{
LibGUI::EventPacket packet;
packet.type = LibGUI::EventPacket::Type::MouseMoveEvent;
packet.mouse_move_event.x = m_cursor.x - m_focused_window->x();
packet.mouse_move_event.y = m_cursor.y - m_focused_window->y();
send(m_focused_window->client_fd(), &packet, sizeof(packet), 0);
}
}
void WindowServer::on_mouse_scroll(LibInput::MouseScrollEvent event)
{
if (m_focused_window)
{
LibGUI::EventPacket packet;
packet.type = LibGUI::EventPacket::Type::MouseScrollEvent;
packet.mouse_scroll_event = event;
send(m_focused_window->client_fd(), &packet, sizeof(packet), 0);
}
}
void WindowServer::set_focused_window(BAN::RefPtr<Window> window)
{
if (m_focused_window == window)
return;
for (size_t i = m_windows_ordered.size(); i > 0; i--)
{
if (m_windows_ordered[i - 1] == window)
{
m_focused_window = window;
m_windows_ordered.remove(i - 1);
MUST(m_windows_ordered.push_back(window));
invalidate(window->area());
break;
}
}
}
void WindowServer::invalidate(Rectangle area)
{
auto fb_overlap = area.get_overlap(m_framebuffer.area());
if (!fb_overlap.has_value())
return;
area = fb_overlap.release_value();
for (int32_t y = area.y; y < area.y + area.height; y++)
memset(&m_framebuffer.mmap[y * m_framebuffer.width + area.x], 0, area.width * 4);
for (auto& pwindow : m_windows_ordered)
{
auto& window = *pwindow;
auto overlap = window.area().get_overlap(area);
if (!overlap.has_value())
continue;
const int32_t src_x = overlap->x - window.x();
const int32_t src_y = overlap->y - window.y();
for (int32_t y_off = 0; y_off < overlap->height; y_off++)
memcpy(
&m_framebuffer.mmap[(overlap->y + y_off) * m_framebuffer.width + overlap->x],
&window.framebuffer()[(src_y + y_off) * window.width() + src_x],
overlap->width * 4
);
}
Rectangle cursor { m_cursor.x, m_cursor.y, s_cursor_width, s_cursor_height };
auto overlap = cursor.get_overlap(area);
if (overlap.has_value())
{
for (int32_t dy = overlap->y - cursor.y; dy < overlap->height; dy++)
{
for (int32_t dx = overlap->x - cursor.x; dx < overlap->width; dx++)
{
const uint32_t offset = (dy * s_cursor_width + dx) * 4;
uint32_t r = (((s_cursor_data[offset + 0] - 33) << 2) | ((s_cursor_data[offset + 1] - 33) >> 4));
uint32_t g = ((((s_cursor_data[offset + 1] - 33) & 0xF) << 4) | ((s_cursor_data[offset + 2] - 33) >> 2));
uint32_t b = ((((s_cursor_data[offset + 2] - 33) & 0x3) << 6) | ((s_cursor_data[offset + 3] - 33)));
uint32_t color = (r << 16) | (g << 8) | b;
if (color != 0xFF00FF)
m_framebuffer.mmap[(overlap->y + dy) * m_framebuffer.width + (overlap->x + dx)] = color;
}
}
}
uintptr_t mmap_start = reinterpret_cast<uintptr_t>(m_framebuffer.mmap) + area.y * m_framebuffer.width * 4;
uintptr_t mmap_end = mmap_start + (area.height + 1) * m_framebuffer.width * 4;
mmap_start &= ~(uintptr_t)0xFFF;
msync(reinterpret_cast<void*>(mmap_start), mmap_end - mmap_start, MS_SYNC);
}

View File

@ -1,44 +0,0 @@
#pragma once
#include "Framebuffer.h"
#include "Window.h"
#include <BAN/Function.h>
#include <BAN/Iteration.h>
#include <BAN/Vector.h>
#include <BAN/HashMap.h>
#include <LibInput/KeyEvent.h>
#include <LibInput/MouseEvent.h>
class WindowServer
{
public:
WindowServer(Framebuffer& framebuffer)
: m_framebuffer(framebuffer)
, m_cursor({ framebuffer.width / 2, framebuffer.height / 2 })
{
invalidate(m_framebuffer.area());
}
void add_window(int fd, BAN::RefPtr<Window> window);
void for_each_window(const BAN::Function<BAN::Iteration(int, Window&)>& callback);
void on_key_event(LibInput::KeyEvent event);
void on_mouse_button(LibInput::MouseButtonEvent event);
void on_mouse_move(LibInput::MouseMoveEvent event);
void on_mouse_scroll(LibInput::MouseScrollEvent event);
void set_focused_window(BAN::RefPtr<Window> window);
void invalidate(Rectangle area);
private:
Framebuffer& m_framebuffer;
BAN::Vector<BAN::RefPtr<Window>> m_windows_ordered;
BAN::HashMap<int, BAN::RefPtr<Window>> m_windows;
bool m_is_mod_key_held { false };
bool m_is_moving_window { false };
BAN::RefPtr<Window> m_focused_window;
Position m_cursor;
};

View File

@ -1,267 +0,0 @@
#include "WindowServer.h"
#include <BAN/Debug.h>
#include <LibGUI/Window.h>
#include <LibInput/KeyboardLayout.h>
#include <fcntl.h>
#include <stdlib.h>
#include <sys/banan-os.h>
#include <sys/mman.h>
#include <sys/socket.h>
#include <sys/select.h>
#include <sys/stat.h>
#include <sys/un.h>
#include <unistd.h>
int open_server_fd()
{
struct stat st;
if (stat(LibGUI::s_window_server_socket.data(), &st) != -1)
unlink(LibGUI::s_window_server_socket.data());
int server_fd = socket(AF_UNIX, SOCK_SEQPACKET, 0);
if (server_fd == -1)
{
perror("socket");
exit(1);
}
sockaddr_un server_addr;
server_addr.sun_family = AF_UNIX;
strcpy(server_addr.sun_path, LibGUI::s_window_server_socket.data());
if (bind(server_fd, (sockaddr*)&server_addr, sizeof(server_addr)) == -1)
{
perror("bind");
exit(1);
}
if (chmod("/tmp/resolver.sock", 0777) == -1)
{
perror("chmod");
exit(1);
}
if (listen(server_fd, SOMAXCONN) == -1)
{
perror("listen");
exit(1);
}
return server_fd;
}
int main()
{
srand(time(nullptr));
int server_fd = open_server_fd();
auto framebuffer = open_framebuffer();
if (framebuffer.bpp != 32)
{
dwarnln("Window server requires 32 bpp");
return 1;
}
if (tty_ctrl(STDIN_FILENO, TTY_CMD_UNSET, TTY_FLAG_ENABLE_INPUT) == -1)
{
perror("tty_ctrl");
exit(1);
}
atexit([]() { tty_ctrl(STDIN_FILENO, TTY_CMD_SET, TTY_FLAG_ENABLE_INPUT); });
MUST(LibInput::KeyboardLayout::initialize());
MUST(LibInput::KeyboardLayout::get().load_from_file("/usr/share/keymaps/us.keymap"sv));
int keyboard_fd = open("/dev/input0", O_RDONLY);
if (keyboard_fd == -1)
perror("open");
int mouse_fd = open("/dev/input1", O_RDONLY);
if (mouse_fd == -1)
perror("open");
dprintln("Window server started");
for (int i = 0; i < 2; i++)
{
if (fork() == 0)
{
execl("/bin/test-window", "test-window", NULL);
exit(1);
}
}
WindowServer window_server(framebuffer);
for (;;)
{
int max_socket = server_fd;
fd_set fds;
FD_ZERO(&fds);
FD_SET(server_fd, &fds);
if (keyboard_fd != -1)
{
FD_SET(keyboard_fd, &fds);
max_socket = BAN::Math::max(max_socket, keyboard_fd);
}
if (mouse_fd != -1)
{
FD_SET(mouse_fd, &fds);
max_socket = BAN::Math::max(max_socket, mouse_fd);
}
window_server.for_each_window(
[&](int fd, Window&) -> BAN::Iteration
{
FD_SET(fd, &fds);
max_socket = BAN::Math::max(max_socket, fd);
return BAN::Iteration::Continue;
}
);
if (select(max_socket + 1, &fds, nullptr, nullptr, nullptr) == -1)
{
dwarnln("select: {}", strerror(errno));
break;
}
if (FD_ISSET(server_fd, &fds))
{
int window_fd = accept(server_fd, nullptr, nullptr);
if (window_fd == -1)
{
dwarnln("accept: {}", strerror(errno));
continue;
}
auto window = MUST(BAN::RefPtr<Window>::create(window_fd));
window_server.add_window(window_fd, window);
}
if (keyboard_fd != -1 && FD_ISSET(keyboard_fd, &fds))
{
LibInput::RawKeyEvent event;
if (read(keyboard_fd, &event, sizeof(event)) == -1)
{
perror("read");
continue;
}
window_server.on_key_event(LibInput::KeyboardLayout::get().key_event_from_raw(event));
}
if (mouse_fd != -1 && FD_ISSET(mouse_fd, &fds))
{
LibInput::MouseEvent event;
if (read(mouse_fd, &event, sizeof(event)) == -1)
{
perror("read");
continue;
}
switch (event.type)
{
case LibInput::MouseEventType::MouseButtonEvent:
window_server.on_mouse_button(event.button_event);
break;
case LibInput::MouseEventType::MouseMoveEvent:
window_server.on_mouse_move(event.move_event);
break;
case LibInput::MouseEventType::MouseScrollEvent:
window_server.on_mouse_scroll(event.scroll_event);
break;
}
}
window_server.for_each_window(
[&](int fd, Window& window) -> BAN::Iteration
{
if (!FD_ISSET(fd, &fds))
return BAN::Iteration::Continue;
LibGUI::WindowPacket packet;
ssize_t nrecv = recv(fd, &packet, sizeof(packet), 0);
if (nrecv < 0)
dwarnln("recv: {}", strerror(errno));
if (nrecv <= 0)
{
window.mark_deleted();
return BAN::Iteration::Continue;
}
switch (packet.type)
{
case LibGUI::WindowPacketType::CreateWindow:
{
if (nrecv != sizeof(LibGUI::WindowCreatePacket))
{
dwarnln("Invalid WindowCreate packet size");
break;
}
const size_t window_fb_bytes = packet.create.width * packet.create.height * 4;
long smo_key = smo_create(window_fb_bytes, PROT_READ | PROT_WRITE);
if (smo_key == -1)
{
dwarnln("smo_create: {}", strerror(errno));
break;
}
void* smo_address = smo_map(smo_key);
if (smo_address == nullptr)
{
dwarnln("smo_map: {}", strerror(errno));
break;
}
memset(smo_address, 0, window_fb_bytes);
LibGUI::WindowCreateResponse response;
response.framebuffer_smo_key = smo_key;
if (send(fd, &response, sizeof(response), 0) != sizeof(response))
{
dwarnln("send: {}", strerror(errno));
break;
}
window.set_size({
static_cast<int32_t>(packet.create.width),
static_cast<int32_t>(packet.create.height)
}, reinterpret_cast<uint32_t*>(smo_address));
window.set_position({
static_cast<int32_t>(window.width() / 2),
static_cast<int32_t>(window.height() / 2)
});
break;
}
case LibGUI::WindowPacketType::Invalidate:
{
if (nrecv != sizeof(LibGUI::WindowInvalidatePacket))
{
dwarnln("Invalid Invalidate packet size");
break;
}
if (packet.invalidate.x + packet.invalidate.width > window.width() || packet.invalidate.y + packet.invalidate.height > window.height())
{
dwarnln("Invalid Invalidate packet parameters");
break;
}
window_server.invalidate({
window.x() + static_cast<int32_t>(packet.invalidate.x),
window.y() + static_cast<int32_t>(packet.invalidate.y),
static_cast<int32_t>(packet.invalidate.width),
static_cast<int32_t>(packet.invalidate.height),
});
break;
}
default:
dwarnln("Invalid window packet from {}", fd);
}
return BAN::Iteration::Continue;
}
);
}
}

View File

@ -7,7 +7,7 @@
#include <sys/mman.h>
#include <termios.h>
#include <LibInput/MouseEvent.h>
#include <kernel/Input/MouseEvent.h>
framebuffer_info_t fb_info;
void* fb_mmap = nullptr;
@ -137,7 +137,7 @@ int main(int argc, char** argv)
while (true)
{
using namespace LibInput;
using namespace Kernel::Input;
MouseEvent event;
if (read(mouse_fd, &event, sizeof(event)) == -1)

View File

@ -1,16 +0,0 @@
cmake_minimum_required(VERSION 3.26)
project(test-window CXX)
set(SOURCES
main.cpp
)
add_executable(test-window ${SOURCES})
target_compile_options(test-window PUBLIC -O2 -g)
target_link_libraries(test-window PUBLIC libc ban libgui)
add_custom_target(test-window-install
COMMAND ${CMAKE_COMMAND} -E copy ${CMAKE_CURRENT_BINARY_DIR}/test-window ${BANAN_BIN}/
DEPENDS test-window
)

View File

@ -1,61 +0,0 @@
#include <BAN/Debug.h>
#include <LibGUI/Window.h>
#include <stdlib.h>
#include <unistd.h>
void randomize_color(BAN::UniqPtr<LibGUI::Window>& window)
{
uint32_t color = ((rand() % 255) << 16) | ((rand() % 255) << 8) | ((rand() % 255) << 0);
for (uint32_t y = 0; y < window->height(); y++)
for (uint32_t x = 0; x < window->width(); x++)
window->set_pixel(x, y, color);
window->invalidate();
}
int main()
{
timespec ts;
clock_gettime(CLOCK_MONOTONIC, &ts);
srand(ts.tv_nsec);
auto window_or_error = LibGUI::Window::create(300, 200);
if (window_or_error.is_error())
{
dprintln("{}", window_or_error.error());
return 1;
}
auto window = window_or_error.release_value();
window->set_mouse_button_event_callback(
[&](LibGUI::EventPacket::MouseButtonEvent event)
{
if (event.pressed && event.button == LibGUI::EventPacket::MouseButton::Left)
randomize_color(window);
const char* button;
switch (event.button)
{
case LibGUI::EventPacket::MouseButton::Left: button = "left"; break;
case LibGUI::EventPacket::MouseButton::Right: button = "right"; break;
case LibGUI::EventPacket::MouseButton::Middle: button = "middle"; break;
case LibGUI::EventPacket::MouseButton::Extra1: button = "extra1"; break;
case LibGUI::EventPacket::MouseButton::Extra2: button = "extra2"; break;
}
dprintln("mouse button '{}' {} at {}, {}", button, event.pressed ? "pressed" : "released", event.x, event.y);
}
);
randomize_color(window);
for (;;)
{
window->poll_events();
timespec duration;
duration.tv_sec = 0;
duration.tv_nsec = 16'666'666;
nanosleep(&duration, nullptr);
}
}