Explorar o código

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 :^)
Andreas Kling %!s(int64=6) %!d(string=hai) anos
pai
achega
c5a00a56c8

+ 15 - 6
Kernel/RTC.cpp

@@ -64,6 +64,19 @@ static unsigned days_in_years_since_epoch(unsigned year)
     return days;
     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()
 time_t now()
 {
 {
     // FIXME: We should probably do something more robust here.
     // FIXME: We should probably do something more robust here.
@@ -72,12 +85,8 @@ time_t now()
     while (update_in_progress())
     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);
     ASSERT(year >= 2018);
 
 

+ 1 - 0
Kernel/RTC.h

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

+ 0 - 4
Kernel/init.cpp

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

+ 54 - 1
WindowServer/WSMessageLoop.cpp

@@ -110,6 +110,37 @@ void WSMessageLoop::post_message(WSMessageReceiver* receiver, OwnPtr<WSMessage>&
         m_server_process->request_wakeup();
         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()
 void WSMessageLoop::wait_for_message()
 {
 {
     fd_set rfds;
     fd_set rfds;
@@ -123,7 +154,19 @@ void WSMessageLoop::wait_for_message()
     params.writefds = nullptr;
     params.writefds = nullptr;
     params.exceptfds = nullptr;
     params.exceptfds = nullptr;
     struct timeval timeout = { 0, 0 };
     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;
         params.timeout = nullptr;
     else
     else
         params.timeout = &timeout;
         params.timeout = &timeout;
@@ -134,6 +177,16 @@ void WSMessageLoop::wait_for_message()
         ASSERT_NOT_REACHED();
         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))
     if (bitmap.get(m_keyboard_fd))
         drain_keyboard();
         drain_keyboard();
     if (bitmap.get(m_mouse_fd))
     if (bitmap.get(m_mouse_fd))

+ 17 - 0
WindowServer/WSMessageLoop.h

@@ -2,8 +2,10 @@
 
 
 #include "WSMessage.h"
 #include "WSMessage.h"
 #include <AK/Lock.h>
 #include <AK/Lock.h>
+#include <AK/HashMap.h>
 #include <AK/OwnPtr.h>
 #include <AK/OwnPtr.h>
 #include <AK/Vector.h>
 #include <AK/Vector.h>
+#include <AK/Function.h>
 
 
 class WSMessageReceiver;
 class WSMessageReceiver;
 class Process;
 class Process;
@@ -24,6 +26,9 @@ public:
 
 
     void set_server_process(Process& process) { m_server_process = &process; }
     void set_server_process(Process& process) { m_server_process = &process; }
 
 
+    int start_timer(int ms, Function<void()>&&);
+    int stop_timer(int timer_id);
+
 private:
 private:
     void wait_for_message();
     void wait_for_message();
     void drain_mouse();
     void drain_mouse();
@@ -42,4 +47,16 @@ private:
 
 
     int m_keyboard_fd { -1 };
     int m_keyboard_fd { -1 };
     int m_mouse_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;
 };
 };

+ 18 - 3
WindowServer/WSWindowManager.cpp

@@ -14,6 +14,7 @@
 #include "WSMenu.h"
 #include "WSMenu.h"
 #include "WSMenuBar.h"
 #include "WSMenuBar.h"
 #include "WSMenuItem.h"
 #include "WSMenuItem.h"
+#include <Kernel/RTC.h>
 
 
 //#define DEBUG_COUNTERS
 //#define DEBUG_COUNTERS
 //#define DEBUG_WID_IN_TITLE_BAR
 //#define DEBUG_WID_IN_TITLE_BAR
@@ -210,6 +211,10 @@ WSWindowManager::WSWindowManager()
     // NOTE: This ensures that the system menu has the correct dimensions.
     // NOTE: This ensures that the system menu has the correct dimensions.
     set_current_menubar(nullptr);
     set_current_menubar(nullptr);
 
 
+    WSMessageLoop::the().start_timer(300, [this] {
+        invalidate(menubar_rect());
+    });
+
     invalidate();
     invalidate();
     compose();
     compose();
 }
 }
@@ -226,16 +231,20 @@ void WSWindowManager::for_each_active_menubar_menu(Callback callback)
         m_current_menubar->for_each_menu(callback);
         m_current_menubar->for_each_menu(callback);
 }
 }
 
 
+int WSWindowManager::menubar_menu_margin() const
+{
+    return 16;
+}
+
 void WSWindowManager::set_current_menubar(WSMenuBar* menubar)
 void WSWindowManager::set_current_menubar(WSMenuBar* menubar)
 {
 {
     LOCKER(m_lock);
     LOCKER(m_lock);
     m_current_menubar = menubar;
     m_current_menubar = menubar;
     dbgprintf("[WM] Current menubar is now %p\n", 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) {
     for_each_active_menubar_menu([&] (WSMenu& menu) {
         int text_width = font().width(menu.name());
         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() } });
         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);
         next_menu_location.move_by(menu.rect_in_menubar().width(), 0);
         return true;
         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);
         m_back_painter->draw_text(menu.text_rect_in_menubar(), menu.name(), TextAlignment::CenterLeft, text_color);
         return true;
         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()
 void WSWindowManager::draw_cursor()

+ 1 - 0
WindowServer/WSWindowManager.h

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