WindowServer: Put a clock in the top right corner of the screen.

This way we don't even need the Clock app anymore. Very cool :^)
This commit is contained in:
Andreas Kling 2019-02-13 09:10:32 +01:00
parent cac8153436
commit c5a00a56c8
Notes: sideshowbarker 2024-07-19 15:45:43 +09:00
7 changed files with 106 additions and 14 deletions

View file

@ -64,6 +64,19 @@ static unsigned days_in_years_since_epoch(unsigned year)
return days;
}
void read_registers(unsigned& year, unsigned& month, unsigned& day, unsigned& hour, unsigned& minute, unsigned& second)
{
while (update_in_progress())
;
year = (CMOS::read(0x32) * 100) + CMOS::read(0x09);
month = CMOS::read(0x08);
day = CMOS::read(0x07);
hour = CMOS::read(0x04);
minute = CMOS::read(0x02);
second = CMOS::read(0x00);
}
time_t now()
{
// FIXME: We should probably do something more robust here.
@ -72,12 +85,8 @@ time_t now()
while (update_in_progress())
;
unsigned year = (CMOS::read(0x32) * 100) + CMOS::read(0x09);
unsigned month = CMOS::read(0x08);
unsigned day = CMOS::read(0x07);
unsigned hour = CMOS::read(0x04);
unsigned minute = CMOS::read(0x02);
unsigned second = CMOS::read(0x00);
unsigned year, month, day, hour, minute, second;
read_registers(year, month, day, hour, minute, second);
ASSERT(year >= 2018);

View file

@ -7,6 +7,7 @@ namespace RTC {
void initialize();
time_t now();
time_t boot_time();
void read_registers(unsigned& year, unsigned& month, unsigned& day, unsigned& hour, unsigned& minute, unsigned& second);
}

View file

@ -28,7 +28,6 @@
//#define SPAWN_GUITEST
#define SPAWN_LAUNCHER
//#define SPAWN_GUITEST2
#define SPAWN_CLOCK
#define SPAWN_FILE_MANAGER
//#define SPAWN_FONTEDITOR
//#define SPAWN_MULTIPLE_SHELLS
@ -116,9 +115,6 @@ static void init_stage2()
#ifdef SPAWN_LAUNCHER
Process::create_user_process("/bin/Launcher", (uid_t)100, (gid_t)100, (pid_t)0, error, { }, { }, tty0);
#endif
#ifdef SPAWN_CLOCK
Process::create_user_process("/bin/Clock", (uid_t)100, (gid_t)100, (pid_t)0, error, { }, { }, tty0);
#endif
#ifdef SPAWN_FILE_MANAGER
Process::create_user_process("/bin/FileManager", (uid_t)100, (gid_t)100, (pid_t)0, error, { }, { }, tty0);
#endif

View file

@ -110,6 +110,37 @@ void WSMessageLoop::post_message(WSMessageReceiver* receiver, OwnPtr<WSMessage>&
m_server_process->request_wakeup();
}
void WSMessageLoop::Timer::reload()
{
struct timeval now;
current->sys$gettimeofday(&now);
next_fire_time = {
now.tv_sec + (interval / 1000),
now.tv_usec + (interval % 1000)
};
}
int WSMessageLoop::start_timer(int interval, Function<void()>&& callback)
{
auto timer = make<Timer>();
int timer_id = m_next_timer_id++;
timer->timer_id = timer_id;
timer->callback = move(callback);
timer->interval = interval;
timer->reload();
m_timers.set(timer_id, move(timer));
return timer_id;
}
int WSMessageLoop::stop_timer(int timer_id)
{
auto it = m_timers.find(timer_id);
if (it == m_timers.end())
return -1;
m_timers.remove(it);
return 0;
}
void WSMessageLoop::wait_for_message()
{
fd_set rfds;
@ -123,7 +154,19 @@ void WSMessageLoop::wait_for_message()
params.writefds = nullptr;
params.exceptfds = nullptr;
struct timeval timeout = { 0, 0 };
if (m_queued_messages.is_empty())
bool had_any_timer = false;
for (auto& it : m_timers) {
auto& timer = *it.value;
if (!had_any_timer) {
timeout = timer.next_fire_time;
continue;
}
if (timer.next_fire_time.tv_sec > timeout.tv_sec || (timer.next_fire_time.tv_sec == timeout.tv_sec && timer.next_fire_time.tv_usec > timeout.tv_usec))
timeout = timer.next_fire_time;
}
if (m_timers.is_empty() && m_queued_messages.is_empty())
params.timeout = nullptr;
else
params.timeout = &timeout;
@ -134,6 +177,16 @@ void WSMessageLoop::wait_for_message()
ASSERT_NOT_REACHED();
}
struct timeval now;
current->sys$gettimeofday(&now);
for (auto& it : m_timers) {
auto& timer = *it.value;
if (now.tv_sec > timer.next_fire_time.tv_sec || (now.tv_sec == timer.next_fire_time.tv_sec && now.tv_usec > timer.next_fire_time.tv_usec)) {
timer.callback();
timer.reload();
}
}
if (bitmap.get(m_keyboard_fd))
drain_keyboard();
if (bitmap.get(m_mouse_fd))

View file

@ -2,8 +2,10 @@
#include "WSMessage.h"
#include <AK/Lock.h>
#include <AK/HashMap.h>
#include <AK/OwnPtr.h>
#include <AK/Vector.h>
#include <AK/Function.h>
class WSMessageReceiver;
class Process;
@ -24,6 +26,9 @@ public:
void set_server_process(Process& process) { m_server_process = &process; }
int start_timer(int ms, Function<void()>&&);
int stop_timer(int timer_id);
private:
void wait_for_message();
void drain_mouse();
@ -42,4 +47,16 @@ private:
int m_keyboard_fd { -1 };
int m_mouse_fd { -1 };
struct Timer {
void reload();
int timer_id { 0 };
int interval { 0 };
struct timeval next_fire_time { 0, 0 };
Function<void()> callback;
};
int m_next_timer_id { 1 };
HashMap<int, OwnPtr<Timer>> m_timers;
};

View file

@ -14,6 +14,7 @@
#include "WSMenu.h"
#include "WSMenuBar.h"
#include "WSMenuItem.h"
#include <Kernel/RTC.h>
//#define DEBUG_COUNTERS
//#define DEBUG_WID_IN_TITLE_BAR
@ -210,6 +211,10 @@ WSWindowManager::WSWindowManager()
// NOTE: This ensures that the system menu has the correct dimensions.
set_current_menubar(nullptr);
WSMessageLoop::the().start_timer(300, [this] {
invalidate(menubar_rect());
});
invalidate();
compose();
}
@ -226,16 +231,20 @@ void WSWindowManager::for_each_active_menubar_menu(Callback callback)
m_current_menubar->for_each_menu(callback);
}
int WSWindowManager::menubar_menu_margin() const
{
return 16;
}
void WSWindowManager::set_current_menubar(WSMenuBar* menubar)
{
LOCKER(m_lock);
m_current_menubar = menubar;
dbgprintf("[WM] Current menubar is now %p\n", menubar);
int menu_margin = 16;
Point next_menu_location { menu_margin / 2, 3 };
Point next_menu_location { menubar_menu_margin() / 2, 3 };
for_each_active_menubar_menu([&] (WSMenu& menu) {
int text_width = font().width(menu.name());
menu.set_rect_in_menubar({ next_menu_location.x() - menu_margin / 2, 0, text_width + menu_margin, menubar_rect().height() - 1 });
menu.set_rect_in_menubar({ next_menu_location.x() - menubar_menu_margin() / 2, 0, text_width + menubar_menu_margin(), menubar_rect().height() - 1 });
menu.set_text_rect_in_menubar({ next_menu_location, { text_width, font().glyph_height() } });
next_menu_location.move_by(menu.rect_in_menubar().width(), 0);
return true;
@ -682,6 +691,12 @@ void WSWindowManager::draw_menubar()
m_back_painter->draw_text(menu.text_rect_in_menubar(), menu.name(), TextAlignment::CenterLeft, text_color);
return true;
});
unsigned year, month, day, hour, minute, second;
RTC::read_registers(year, month, day, hour, minute, second);
auto time_text = String::format("%04u-%02u-%02u %02u:%02u:%02u", year, month, day, hour, minute, second);
auto time_rect = menubar_rect().translated(-(menubar_menu_margin() / 2), 0);
m_back_painter->draw_text(time_rect, time_text, TextAlignment::CenterRight, Color::Black);
}
void WSWindowManager::draw_cursor()

View file

@ -57,6 +57,7 @@ public:
void close_menu(WSMenu&);
Color menu_selection_color() const { return m_menu_selection_color; }
int menubar_menu_margin() const;
int api$menubar_create();
int api$menubar_destroy(int menubar_id);