mirror of
https://github.com/RGBCube/serenity
synced 2025-05-25 21:05:07 +00:00
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:
parent
cac8153436
commit
c5a00a56c8
7 changed files with 106 additions and 14 deletions
|
@ -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 year, month, day, hour, minute, second;
|
||||||
unsigned month = CMOS::read(0x08);
|
read_registers(year, month, day, hour, minute, second);
|
||||||
unsigned day = CMOS::read(0x07);
|
|
||||||
unsigned hour = CMOS::read(0x04);
|
|
||||||
unsigned minute = CMOS::read(0x02);
|
|
||||||
unsigned second = CMOS::read(0x00);
|
|
||||||
|
|
||||||
ASSERT(year >= 2018);
|
ASSERT(year >= 2018);
|
||||||
|
|
||||||
|
|
|
@ -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);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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))
|
||||||
|
|
|
@ -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;
|
||||||
};
|
};
|
||||||
|
|
|
@ -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 { menubar_menu_margin() / 2, 3 };
|
||||||
Point next_menu_location { 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()
|
||||||
|
|
|
@ -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);
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue