diff --git a/Kernel/RTC.cpp b/Kernel/RTC.cpp index 17bc7e663ac..acb6186d408 100644 --- a/Kernel/RTC.cpp +++ b/Kernel/RTC.cpp @@ -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); diff --git a/Kernel/RTC.h b/Kernel/RTC.h index f321ffd806f..54d9c9af507 100644 --- a/Kernel/RTC.h +++ b/Kernel/RTC.h @@ -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); } diff --git a/Kernel/init.cpp b/Kernel/init.cpp index ae7f5e8783a..9fc605a2c06 100644 --- a/Kernel/init.cpp +++ b/Kernel/init.cpp @@ -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 diff --git a/WindowServer/WSMessageLoop.cpp b/WindowServer/WSMessageLoop.cpp index f9535880f67..536f1f52929 100644 --- a/WindowServer/WSMessageLoop.cpp +++ b/WindowServer/WSMessageLoop.cpp @@ -110,6 +110,37 @@ void WSMessageLoop::post_message(WSMessageReceiver* receiver, OwnPtr& 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&& callback) +{ + auto timer = make(); + 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)) diff --git a/WindowServer/WSMessageLoop.h b/WindowServer/WSMessageLoop.h index 3a81ccb4dc8..a889e066e47 100644 --- a/WindowServer/WSMessageLoop.h +++ b/WindowServer/WSMessageLoop.h @@ -2,8 +2,10 @@ #include "WSMessage.h" #include +#include #include #include +#include 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&&); + 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 callback; + }; + + int m_next_timer_id { 1 }; + HashMap> m_timers; }; diff --git a/WindowServer/WSWindowManager.cpp b/WindowServer/WSWindowManager.cpp index 5816adca85c..35dadee6d40 100644 --- a/WindowServer/WSWindowManager.cpp +++ b/WindowServer/WSWindowManager.cpp @@ -14,6 +14,7 @@ #include "WSMenu.h" #include "WSMenuBar.h" #include "WSMenuItem.h" +#include //#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() diff --git a/WindowServer/WSWindowManager.h b/WindowServer/WSWindowManager.h index a97f9cb004c..10c7ceac4e0 100644 --- a/WindowServer/WSWindowManager.h +++ b/WindowServer/WSWindowManager.h @@ -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);