#include "LibGUI/Window.h" #include #include #include #include #include #include #include #include namespace LibGUI { Window::~Window() { munmap(m_framebuffer, m_width * m_height * 4); close(m_server_fd); } BAN::ErrorOr> Window::create(uint32_t width, uint32_t height, BAN::StringView title) { if (title.size() >= sizeof(WindowCreatePacket::title)) return BAN::Error::from_errno(EINVAL); int server_fd = socket(AF_UNIX, SOCK_SEQPACKET, 0); if (server_fd == -1) return BAN::Error::from_errno(errno); timespec start_time; clock_gettime(CLOCK_MONOTONIC, &start_time); for (;;) { 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)) == 0) break; timespec current_time; clock_gettime(CLOCK_MONOTONIC, ¤t_time); time_t duration_s = (current_time.tv_sec - start_time.tv_sec) + (current_time.tv_nsec >= start_time.tv_nsec); if (duration_s > 10) { close(server_fd); return BAN::Error::from_errno(ETIMEDOUT); } timespec sleep_time; sleep_time.tv_sec = 0; sleep_time.tv_nsec = 1'000'000; nanosleep(&sleep_time, nullptr); } WindowCreatePacket packet; packet.width = width; packet.height = height; strncpy(packet.title, title.data(), title.size()); packet.title[title.size()] = '\0'; 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::create( server_fd, static_cast(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::DestroyWindow: exit(1); case EventPacket::Type::CloseWindow: if (m_close_window_event_callback) m_close_window_event_callback(); else exit(0); break; 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; } } } }