WindowServer: Add support for background images
WindowServer now looks in _$HOME/.config/WindowServer.conf_ for a configuration file that can specify a background image. Also add default background image /usr/share/images/sample.ppm to the base sysroot provided in the git repo.
This commit is contained in:
		
							parent
							
								
									14d4551476
								
							
						
					
					
						commit
						dd64e2060e
					
				
										
											Binary file not shown.
										
									
								
							| 
						 | 
					@ -11,7 +11,7 @@ set(SOURCES
 | 
				
			||||||
 | 
					
 | 
				
			||||||
add_executable(WindowServer ${SOURCES})
 | 
					add_executable(WindowServer ${SOURCES})
 | 
				
			||||||
target_compile_options(WindowServer PUBLIC -O2 -g)
 | 
					target_compile_options(WindowServer PUBLIC -O2 -g)
 | 
				
			||||||
target_link_libraries(WindowServer PUBLIC libc ban libfont libgui libinput)
 | 
					target_link_libraries(WindowServer PUBLIC libc ban libfont libgui libimage libinput)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
add_custom_target(WindowServer-install
 | 
					add_custom_target(WindowServer-install
 | 
				
			||||||
	COMMAND ${CMAKE_COMMAND} -E copy ${CMAKE_CURRENT_BINARY_DIR}/WindowServer ${BANAN_BIN}/
 | 
						COMMAND ${CMAKE_COMMAND} -E copy ${CMAKE_CURRENT_BINARY_DIR}/WindowServer ${BANAN_BIN}/
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -11,6 +11,15 @@
 | 
				
			||||||
#include <sys/mman.h>
 | 
					#include <sys/mman.h>
 | 
				
			||||||
#include <sys/socket.h>
 | 
					#include <sys/socket.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					BAN::ErrorOr<void> WindowServer::set_background_image(BAN::UniqPtr<LibImage::Image> image)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						if (image->width() != (uint64_t)m_framebuffer.width || image->height() != (uint64_t)m_framebuffer.height)
 | 
				
			||||||
 | 
							image = TRY(image->resize(m_framebuffer.width, m_framebuffer.height));
 | 
				
			||||||
 | 
						m_background_image = BAN::move(image);
 | 
				
			||||||
 | 
						invalidate(m_framebuffer.area());
 | 
				
			||||||
 | 
						return {};
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void WindowServer::on_window_packet(int fd, LibGUI::WindowPacket packet)
 | 
					void WindowServer::on_window_packet(int fd, LibGUI::WindowPacket packet)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	switch (packet.type)
 | 
						switch (packet.type)
 | 
				
			||||||
| 
						 | 
					@ -270,8 +279,19 @@ void WindowServer::invalidate(Rectangle area)
 | 
				
			||||||
		return;
 | 
							return;
 | 
				
			||||||
	area = fb_overlap.release_value();
 | 
						area = fb_overlap.release_value();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (m_background_image)
 | 
				
			||||||
 | 
						{
 | 
				
			||||||
 | 
							ASSERT(m_background_image->width() == (uint64_t)m_framebuffer.width);
 | 
				
			||||||
 | 
							ASSERT(m_background_image->height() == (uint64_t)m_framebuffer.height);
 | 
				
			||||||
 | 
							for (int32_t y = area.y; y < area.y + area.height; y++)
 | 
				
			||||||
 | 
								for (int32_t x = area.x; x < area.x + area.width; x++)
 | 
				
			||||||
 | 
									m_framebuffer.mmap[y * m_framebuffer.width + x] = m_background_image->get_color(x, y).as_rgba();
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						else
 | 
				
			||||||
 | 
						{
 | 
				
			||||||
		for (int32_t y = area.y; y < area.y + area.height; y++)
 | 
							for (int32_t y = area.y; y < area.y + area.height; y++)
 | 
				
			||||||
			memset(&m_framebuffer.mmap[y * m_framebuffer.width + area.x], 0x10, area.width * 4);
 | 
								memset(&m_framebuffer.mmap[y * m_framebuffer.width + area.x], 0x10, area.width * 4);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	for (auto& pwindow : m_client_windows)
 | 
						for (auto& pwindow : m_client_windows)
 | 
				
			||||||
	{
 | 
						{
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -10,6 +10,7 @@
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#include <LibFont/Font.h>
 | 
					#include <LibFont/Font.h>
 | 
				
			||||||
#include <LibGUI/Window.h>
 | 
					#include <LibGUI/Window.h>
 | 
				
			||||||
 | 
					#include <LibImage/Image.h>
 | 
				
			||||||
#include <LibInput/KeyEvent.h>
 | 
					#include <LibInput/KeyEvent.h>
 | 
				
			||||||
#include <LibInput/MouseEvent.h>
 | 
					#include <LibInput/MouseEvent.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -26,6 +27,8 @@ public:
 | 
				
			||||||
		invalidate(m_framebuffer.area());
 | 
							invalidate(m_framebuffer.area());
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						BAN::ErrorOr<void> set_background_image(BAN::UniqPtr<LibImage::Image>);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	void on_window_packet(int fd, LibGUI::WindowPacket);
 | 
						void on_window_packet(int fd, LibGUI::WindowPacket);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	void on_key_event(LibInput::KeyEvent event);
 | 
						void on_key_event(LibInput::KeyEvent event);
 | 
				
			||||||
| 
						 | 
					@ -50,6 +53,8 @@ private:
 | 
				
			||||||
	BAN::Vector<BAN::RefPtr<Window>> m_client_windows;
 | 
						BAN::Vector<BAN::RefPtr<Window>> m_client_windows;
 | 
				
			||||||
	BAN::Vector<int> m_client_fds;
 | 
						BAN::Vector<int> m_client_fds;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						BAN::UniqPtr<LibImage::Image> m_background_image;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	bool m_is_mod_key_held { false };
 | 
						bool m_is_mod_key_held { false };
 | 
				
			||||||
	bool m_is_moving_window { false };
 | 
						bool m_is_moving_window { false };
 | 
				
			||||||
	BAN::RefPtr<Window> m_focused_window;
 | 
						BAN::RefPtr<Window> m_focused_window;
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1,6 +1,7 @@
 | 
				
			||||||
#include "WindowServer.h"
 | 
					#include "WindowServer.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#include <BAN/Debug.h>
 | 
					#include <BAN/Debug.h>
 | 
				
			||||||
 | 
					#include <BAN/ScopeGuard.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#include <LibGUI/Window.h>
 | 
					#include <LibGUI/Window.h>
 | 
				
			||||||
#include <LibInput/KeyboardLayout.h>
 | 
					#include <LibInput/KeyboardLayout.h>
 | 
				
			||||||
| 
						 | 
					@ -15,6 +16,88 @@
 | 
				
			||||||
#include <sys/un.h>
 | 
					#include <sys/un.h>
 | 
				
			||||||
#include <unistd.h>
 | 
					#include <unistd.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					struct Config
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						BAN::UniqPtr<LibImage::Image> background_image;
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					BAN::Optional<BAN::String> file_read_line(FILE* file)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						BAN::String line;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						char buffer[128];
 | 
				
			||||||
 | 
						while (fgets(buffer, sizeof(buffer), file))
 | 
				
			||||||
 | 
						{
 | 
				
			||||||
 | 
							MUST(line.append(buffer));
 | 
				
			||||||
 | 
							if (line.back() == '\n')
 | 
				
			||||||
 | 
							{
 | 
				
			||||||
 | 
								line.pop_back();
 | 
				
			||||||
 | 
								return BAN::move(line);
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (line.empty())
 | 
				
			||||||
 | 
							return {};
 | 
				
			||||||
 | 
						return BAN::move(line);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Config parse_config()
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						Config config;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						auto home_env = getenv("HOME");
 | 
				
			||||||
 | 
						if (!home_env)
 | 
				
			||||||
 | 
						{
 | 
				
			||||||
 | 
							dprintln("HOME environment variable not set");
 | 
				
			||||||
 | 
							return config;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						auto config_path = BAN::String::formatted("{}/.config/WindowServer.conf", home_env);
 | 
				
			||||||
 | 
						FILE* fconfig = fopen(config_path.data(), "r");
 | 
				
			||||||
 | 
						if (!fconfig)
 | 
				
			||||||
 | 
						{
 | 
				
			||||||
 | 
							dprintln("Could not open '{}'", config_path);
 | 
				
			||||||
 | 
							return config;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						BAN::ScopeGuard _([fconfig] { fclose(fconfig); });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						while (true)
 | 
				
			||||||
 | 
						{
 | 
				
			||||||
 | 
							auto line = file_read_line(fconfig);
 | 
				
			||||||
 | 
							if (!line.has_value())
 | 
				
			||||||
 | 
								break;
 | 
				
			||||||
 | 
							if (line->empty())
 | 
				
			||||||
 | 
								continue;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							auto parts = MUST(line->sv().split('='));
 | 
				
			||||||
 | 
							if (parts.size() != 2)
 | 
				
			||||||
 | 
							{
 | 
				
			||||||
 | 
								dwarnln("Invalid config line: {}", line.value());
 | 
				
			||||||
 | 
								break;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							auto variable = parts[0];
 | 
				
			||||||
 | 
							auto value = parts[1];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							if (variable == "bg"sv)
 | 
				
			||||||
 | 
							{
 | 
				
			||||||
 | 
								auto image = LibImage::Image::load_from_file(value);
 | 
				
			||||||
 | 
								if (image.is_error())
 | 
				
			||||||
 | 
									dwarnln("Could not load image: {}", image.error());
 | 
				
			||||||
 | 
								else
 | 
				
			||||||
 | 
									config.background_image = image.release_value();
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							else
 | 
				
			||||||
 | 
							{
 | 
				
			||||||
 | 
								dwarnln("Unknown config variable: {}", variable);
 | 
				
			||||||
 | 
								break;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return config;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
int open_server_fd()
 | 
					int open_server_fd()
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	struct stat st;
 | 
						struct stat st;
 | 
				
			||||||
| 
						 | 
					@ -91,7 +174,13 @@ int main()
 | 
				
			||||||
	window_packet_sizes[LibGUI::WindowPacketType::Invalidate]	= sizeof(LibGUI::WindowInvalidatePacket);
 | 
						window_packet_sizes[LibGUI::WindowPacketType::Invalidate]	= sizeof(LibGUI::WindowInvalidatePacket);
 | 
				
			||||||
	static_assert(LibGUI::WindowPacketType::COUNT == 3);
 | 
						static_assert(LibGUI::WindowPacketType::COUNT == 3);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						auto config = parse_config();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	WindowServer window_server(framebuffer);
 | 
						WindowServer window_server(framebuffer);
 | 
				
			||||||
 | 
						if (config.background_image)
 | 
				
			||||||
 | 
							if (auto ret = window_server.set_background_image(BAN::move(config.background_image)); ret.is_error())
 | 
				
			||||||
 | 
								dwarnln("Could not set background image: {}", ret.error());
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	while (!window_server.is_stopped())
 | 
						while (!window_server.is_stopped())
 | 
				
			||||||
	{
 | 
						{
 | 
				
			||||||
		int max_fd = server_fd;
 | 
							int max_fd = server_fd;
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
		Reference in New Issue