Serenity Operating System
at master 160 lines 7.2 kB view raw
1/* 2 * Copyright (c) 2018-2021, Andreas Kling <kling@serenityos.org> 3 * 4 * SPDX-License-Identifier: BSD-2-Clause 5 */ 6 7#include "AppletManager.h" 8#include "Compositor.h" 9#include "EventLoop.h" 10#include "Screen.h" 11#include "WindowManager.h" 12#include <Kernel/API/Graphics.h> 13#include <LibCore/ConfigFile.h> 14#include <LibCore/DeprecatedFile.h> 15#include <LibCore/DirIterator.h> 16#include <LibCore/System.h> 17#include <LibGfx/Palette.h> 18#include <LibGfx/SystemTheme.h> 19#include <LibMain/Main.h> 20#include <signal.h> 21 22namespace WindowServer { 23RefPtr<Core::ConfigFile> g_config; 24} 25 26ErrorOr<int> serenity_main(Main::Arguments) 27{ 28 TRY(Core::System::pledge("stdio video thread sendfd recvfd accept rpath wpath cpath unix proc sigaction exec tty")); 29 TRY(Core::System::unveil("/res", "r")); 30 TRY(Core::System::unveil("/tmp", "cw")); 31 TRY(Core::System::unveil("/etc/WindowServer.ini", "rwc")); 32 TRY(Core::System::unveil("/etc/Keyboard.ini", "r")); 33 TRY(Core::System::unveil("/dev/tty", "rw")); 34 TRY(Core::System::unveil("/dev/gpu/", "rw")); 35 TRY(Core::System::unveil("/dev/input/", "rw")); 36 TRY(Core::System::unveil("/bin/keymap", "x")); 37 TRY(Core::System::unveil("/sys/kernel/keymap", "r")); 38 TRY(Core::System::unveil("/sys/kernel/processes", "r")); 39 TRY(Core::System::unveil("/etc/passwd", "r")); 40 41 struct sigaction act = {}; 42 act.sa_flags = SA_NOCLDWAIT; 43 act.sa_handler = SIG_IGN; 44 TRY(Core::System::sigaction(SIGCHLD, &act, nullptr)); 45 TRY(Core::System::pledge("stdio video thread sendfd recvfd accept rpath wpath cpath unix proc exec tty")); 46 47 WindowServer::g_config = TRY(Core::ConfigFile::open("/etc/WindowServer.ini", Core::ConfigFile::AllowWriting::Yes)); 48 auto theme_name = WindowServer::g_config->read_entry("Theme", "Name", "Default"); 49 50 Optional<DeprecatedString> custom_color_scheme_path = OptionalNone(); 51 if (WindowServer::g_config->read_bool_entry("Theme", "LoadCustomColorScheme", false)) 52 custom_color_scheme_path = WindowServer::g_config->read_entry("Theme", "CustomColorSchemePath"); 53 54 auto theme = TRY(Gfx::load_system_theme(DeprecatedString::formatted("/res/themes/{}.ini", theme_name), custom_color_scheme_path)); 55 Gfx::set_system_theme(theme); 56 auto palette = Gfx::PaletteImpl::create_with_anonymous_buffer(theme); 57 58 auto default_font_query = WindowServer::g_config->read_entry("Fonts", "Default", "Katica 10 400 0"); 59 auto fixed_width_font_query = WindowServer::g_config->read_entry("Fonts", "FixedWidth", "Csilla 10 400 0"); 60 auto window_title_font_query = WindowServer::g_config->read_entry("Fonts", "WindowTitle", "Katica 10 700 0"); 61 62 Gfx::FontDatabase::set_default_font_query(default_font_query); 63 Gfx::FontDatabase::set_fixed_width_font_query(fixed_width_font_query); 64 Gfx::FontDatabase::set_window_title_font_query(window_title_font_query); 65 66 { 67 // FIXME: Map switched tty from screens. 68 // FIXME: Gracefully cleanup the TTY graphics mode. 69 int tty_fd = TRY(Core::System::open("/dev/tty"sv, O_RDWR)); 70 TRY(Core::System::ioctl(tty_fd, KDSETMODE, KD_GRAPHICS)); 71 TRY(Core::System::close(tty_fd)); 72 } 73 74 WindowServer::EventLoop loop; 75 76 TRY(Core::System::pledge("stdio video thread sendfd recvfd accept rpath wpath cpath unix proc exec")); 77 78 // First check which screens are explicitly configured 79 { 80 AK::HashTable<DeprecatedString> fb_devices_configured; 81 WindowServer::ScreenLayout screen_layout; 82 DeprecatedString error_msg; 83 84 auto add_unconfigured_display_connector_devices = [&]() -> ErrorOr<void> { 85 // Enumerate the /dev/gpu/connectorX devices and try to set up any ones we find that we haven't already used 86 Core::DirIterator di("/dev/gpu", Core::DirIterator::SkipParentAndBaseDir); 87 while (di.has_next()) { 88 auto path = di.next_path(); 89 if (!path.starts_with("connector"sv)) 90 continue; 91 auto full_path = DeprecatedString::formatted("/dev/gpu/{}", path); 92 if (!Core::DeprecatedFile::is_device(full_path)) 93 continue; 94 auto display_connector_fd = TRY(Core::System::open(full_path, O_RDWR | O_CLOEXEC)); 95 if (int rc = graphics_connector_set_responsible(display_connector_fd); rc != 0) 96 return Error::from_syscall("graphics_connector_set_responsible"sv, rc); 97 TRY(Core::System::close(display_connector_fd)); 98 if (fb_devices_configured.find(full_path) != fb_devices_configured.end()) 99 continue; 100 if (!screen_layout.try_auto_add_display_connector(full_path)) 101 dbgln("Could not auto-add display connector device {} to screen layout", full_path); 102 } 103 return {}; 104 }; 105 106 auto apply_and_generate_generic_screen_layout = [&]() -> ErrorOr<bool> { 107 screen_layout = {}; 108 fb_devices_configured = {}; 109 110 TRY(add_unconfigured_display_connector_devices()); 111 if (!WindowServer::Screen::apply_layout(move(screen_layout), error_msg)) { 112 dbgln("Failed to apply generated fallback screen layout: {}", error_msg); 113 return false; 114 } 115 116 dbgln("Applied generated fallback screen layout!"); 117 return true; 118 }; 119 120 if (screen_layout.load_config(*WindowServer::g_config, &error_msg)) { 121 for (auto& screen_info : screen_layout.screens) 122 if (screen_info.mode == WindowServer::ScreenLayout::Screen::Mode::Device) 123 fb_devices_configured.set(screen_info.device.value()); 124 125 TRY(add_unconfigured_display_connector_devices()); 126 127 if (!WindowServer::Screen::apply_layout(move(screen_layout), error_msg)) { 128 dbgln("Error applying screen layout: {}", error_msg); 129 TRY(apply_and_generate_generic_screen_layout()); 130 } 131 } else { 132 dbgln("Error loading screen configuration: {}", error_msg); 133 TRY(apply_and_generate_generic_screen_layout()); 134 } 135 } 136 137 auto& screen_input = WindowServer::ScreenInput::the(); 138 screen_input.set_cursor_location(WindowServer::Screen::main().rect().center()); 139 double f = atof(WindowServer::g_config->read_entry("Mouse", "AccelerationFactor", "1.0").characters()); 140 if (f < WindowServer::mouse_accel_min || f > WindowServer::mouse_accel_max) { 141 dbgln("Mouse.AccelerationFactor out of range resetting to 1.0"); 142 f = 1.0; 143 WindowServer::g_config->write_entry("Mouse", "AccelerationFactor", "1.0"); 144 } 145 screen_input.set_acceleration_factor(f); 146 screen_input.set_scroll_step_size(WindowServer::g_config->read_num_entry("Mouse", "ScrollStepSize", 4)); 147 148 WindowServer::Compositor::the(); 149 auto wm = WindowServer::WindowManager::construct(*palette); 150 auto am = WindowServer::AppletManager::construct(); 151 auto mm = WindowServer::MenuManager::construct(); 152 153 TRY(Core::System::unveil("/tmp", "")); 154 155 TRY(Core::System::unveil(nullptr, nullptr)); 156 157 dbgln("Entering WindowServer main loop"); 158 loop.exec(); 159 VERIFY_NOT_REACHED(); 160}