Serenity Operating System
1/*
2 * Copyright (c) 2021, Liav A. <liavalb@hotmail.co.il>
3 *
4 * SPDX-License-Identifier: BSD-2-Clause
5 */
6
7#include <AK/Singleton.h>
8#include <Kernel/CommandLine.h>
9#include <Kernel/Debug.h>
10#include <Kernel/Devices/DeviceManagement.h>
11#include <Kernel/Graphics/GraphicsManagement.h>
12#include <Kernel/Panic.h>
13#include <Kernel/Sections.h>
14#include <Kernel/TTY/ConsoleManagement.h>
15
16namespace Kernel {
17
18static Singleton<ConsoleManagement> s_the;
19
20void ConsoleManagement::resolution_was_changed()
21{
22 for (auto& console : m_consoles) {
23 console->refresh_after_resolution_change();
24 }
25}
26
27bool ConsoleManagement::is_initialized()
28{
29 if (!s_the.is_initialized())
30 return false;
31 if (s_the->m_consoles.is_empty())
32 return false;
33 if (!s_the->m_active_console)
34 return false;
35 return true;
36}
37
38ConsoleManagement& ConsoleManagement::the()
39{
40 return *s_the;
41}
42
43UNMAP_AFTER_INIT ConsoleManagement::ConsoleManagement()
44{
45}
46
47UNMAP_AFTER_INIT void ConsoleManagement::initialize()
48{
49 for (size_t index = 0; index < s_max_virtual_consoles; index++) {
50 // FIXME: Better determine the debug TTY we chose...
51 if (index == 1) {
52 VERIFY(DeviceManagement::the().is_console_device_attached());
53 m_consoles.append(VirtualConsole::create_with_preset_log(index, DeviceManagement::the().console_device().logbuffer()));
54 continue;
55 }
56 m_consoles.append(VirtualConsole::create(index));
57 }
58 // Note: By default the active console is the first one.
59 auto tty_number = kernel_command_line().switch_to_tty();
60 if (tty_number > m_consoles.size()) {
61 PANIC("Switch to tty value is invalid: {} ", tty_number);
62 }
63 m_active_console = m_consoles[tty_number];
64 SpinlockLocker lock(m_lock);
65 m_active_console->set_active(true);
66 if (!m_active_console->is_graphical())
67 m_active_console->clear();
68}
69
70void ConsoleManagement::switch_to(unsigned index)
71{
72 SpinlockLocker lock(m_lock);
73 VERIFY(m_active_console);
74 VERIFY(index < m_consoles.size());
75 if (m_active_console->index() == index)
76 return;
77
78 bool was_graphical = m_active_console->is_graphical();
79 m_active_console->set_active(false);
80 m_active_console = m_consoles[index];
81 dbgln_if(VIRTUAL_CONSOLE_DEBUG, "Console: Switch to {}", index);
82
83 // Before setting current console to be "active", switch between graphical mode to "textual" mode
84 // if needed. This will ensure we clear the screen and also that WindowServer won't print anything
85 // in between.
86 if (m_active_console->is_graphical() && !was_graphical) {
87 m_active_console->set_active(true);
88 GraphicsManagement::the().activate_graphical_mode();
89 return;
90 } else if (!m_active_console->is_graphical() && was_graphical) {
91 GraphicsManagement::the().deactivate_graphical_mode();
92 }
93 m_active_console->set_active(true);
94}
95
96}