Skip to content

Commit

Permalink
wip tray icon
Browse files Browse the repository at this point in the history
  • Loading branch information
Green-Sky committed Jan 10, 2025
1 parent 859ad7d commit 924c969
Show file tree
Hide file tree
Showing 8 changed files with 152 additions and 6 deletions.
2 changes: 2 additions & 0 deletions flake.nix
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,8 @@

pipewire

libayatana-appindicator

# sdl3_image:
libpng
libjpeg
Expand Down
3 changes: 3 additions & 0 deletions src/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,9 @@ target_sources(tomato PUBLIC
./sdl_clipboard_utils.hpp
./sdl_clipboard_utils.cpp

./sys_tray.hpp
./sys_tray.cpp

./chat_gui/theme.hpp
./chat_gui/theme.cpp
./chat_gui/icons/direct.hpp
Expand Down
12 changes: 10 additions & 2 deletions src/main_screen.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,8 @@ MainScreen::MainScreen(SimpleConfigModel&& conf_, SDL_Renderer* renderer_, Theme
contact_tc(tal, sdlrtu),
mil(),
msg_tc(mil, sdlrtu),
si(rmm, cr, SDL_GetRenderWindow(renderer_)),
st(SDL_GetRenderWindow(renderer_)),
si(rmm, cr, SDL_GetRenderWindow(renderer_), &st),
cg(conf, os, rmm, cr, sdlrtu, contact_tc, msg_tc, theme),
sw(conf),
osui(os),
Expand Down Expand Up @@ -248,27 +249,33 @@ bool MainScreen::handleEvent(SDL_Event& e) {
if (e.type == SDL_EVENT_DROP_FILE) {
std::cout << "DROP FILE: " << e.drop.data << "\n";
_dopped_files.emplace_back(e.drop.data);
//cg.sendFilePath(e.drop.data);
_render_interval = 1.f/60.f; // TODO: magic
_time_since_event = 0.f;
return true;
}

if (
e.type == SDL_EVENT_WINDOW_CLOSE_REQUESTED ||
e.type == SDL_EVENT_WINDOW_MINIMIZED ||
e.type == SDL_EVENT_WINDOW_HIDDEN ||
e.type == SDL_EVENT_WINDOW_OCCLUDED // does this trigger on partial occlusion?
) {
auto* window = SDL_GetWindowFromID(e.window.windowID);
auto* event_renderer = SDL_GetRenderer(window);
if (event_renderer != nullptr && event_renderer == renderer) {
if (e.type == SDL_EVENT_WINDOW_CLOSE_REQUESTED) {
// this event only fires if not last window (systrays count as windows)
SDL_HideWindow(window);
}

// our window is now obstructed
if (_window_hidden_ts < e.window.timestamp) {
_window_hidden_ts = e.window.timestamp;
_window_hidden = true;
//std::cout << "TOMAT: window hidden " << e.type << " " << e.window.timestamp << "\n";
}
}
st.update();
return true; // forward?
}

Expand Down Expand Up @@ -296,6 +303,7 @@ bool MainScreen::handleEvent(SDL_Event& e) {
}
_render_interval = 1.f/60.f; // TODO: magic
_time_since_event = 0.f;
st.update(); // TODO: limit this
return true; // forward?
}

Expand Down
2 changes: 2 additions & 0 deletions src/main_screen.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@
#include "./tox_avatar_loader.hpp"
#include "./message_image_loader.hpp"

#include "./sys_tray.hpp"
#include "./status_indicator.hpp"
#include "./chat_gui4.hpp"
#include "./chat_gui/settings_window.hpp"
Expand Down Expand Up @@ -92,6 +93,7 @@ struct MainScreen final : public Screen {
MessageImageLoader mil;
TextureCache<void*, Message3Handle, MessageImageLoader> msg_tc;

SystemTray st;
StatusIndicator si;
ChatGui4 cg;
SettingsWindow sw;
Expand Down
10 changes: 8 additions & 2 deletions src/status_indicator.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -28,16 +28,22 @@ void StatusIndicator::updateState(State state) {
}

SDL_SetWindowIcon(_main_window, surf.get());

if (_tray) {
_tray->setIcon(surf.get());
}
}

StatusIndicator::StatusIndicator(
RegistryMessageModelI& rmm,
Contact3Registry& cr,
SDL_Window* main_window
SDL_Window* main_window,
SystemTray* tray
) :
_rmm(rmm),
_cr(cr),
_main_window(main_window)
_main_window(main_window),
_tray(tray)
{
// start off with base icon
updateState(State::base);
Expand Down
7 changes: 5 additions & 2 deletions src/status_indicator.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@

#include <solanaceae/message3/registry_message_model.hpp>

#include "./sys_tray.hpp"

#include <SDL3/SDL.h>

// service that sets window and tray icon depending on program state
Expand All @@ -11,7 +13,7 @@ class StatusIndicator {
Contact3Registry& _cr;

SDL_Window* _main_window;
// systray ptr here
SystemTray* _tray;

float _cooldown {1.f};

Expand All @@ -27,7 +29,8 @@ class StatusIndicator {
StatusIndicator(
RegistryMessageModelI& rmm,
Contact3Registry& cr,
SDL_Window* main_window
SDL_Window* main_window,
SystemTray* tray = nullptr
);

// does not actually render, just on the render thread
Expand Down
98 changes: 98 additions & 0 deletions src/sys_tray.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,98 @@
#include "./sys_tray.hpp"

#include "./icon_generator.hpp"

#include <memory>
#include <iostream>

SystemTray::SystemTray(SDL_Window* main_window) : _main_window(main_window) {
std::cout << "adding sys tray\n";

_tray = SDL_CreateTray(nullptr, "tomato");
if (_tray == nullptr) {
std::cerr << "failed to create SystemTray: " << SDL_GetError() << "\n";
return;
}

auto* tray_menu = SDL_CreateTrayMenu(_tray);
{
auto* entry_quit = SDL_InsertTrayEntryAt(tray_menu, 0, "Quit Tomato", SDL_TRAYENTRY_BUTTON);
SDL_SetTrayEntryCallback(entry_quit,
+[](void*, SDL_TrayEntry*){
// this is thread safe and triggers the shutdown in the main thread
SDL_Event quit_event;
quit_event.quit = {
SDL_EVENT_QUIT,
0,
SDL_GetTicksNS(),
};
SDL_PushEvent(&quit_event);
}
, nullptr);
}
{
_entry_showhide = SDL_InsertTrayEntryAt(tray_menu, 0, "Hide Tomato", SDL_TRAYENTRY_BUTTON);
SDL_SetTrayEntryCallback(_entry_showhide,
+[](void* userdata, SDL_TrayEntry*){
SDL_HideWindow(static_cast<SystemTray*>(userdata)->_main_window);
}
, this);
}
}

SystemTray::~SystemTray(void) {
if (_tray != nullptr) {
SDL_DestroyTray(_tray);
_tray = nullptr;
}
}

void SystemTray::setIcon(SDL_Surface* surf) {
if (_tray == nullptr) {
return;
}

SDL_SetTrayIcon(_tray, surf);
}

void SystemTray::setStatusText(const std::string& status) {
if (_tray == nullptr) {
return;
}

if (_entry_status == nullptr) {
_entry_status = SDL_InsertTrayEntryAt(SDL_GetTrayMenu(_tray), 0, status.c_str(), SDL_TRAYENTRY_DISABLED);
return;
}

SDL_SetTrayEntryLabel(_entry_status, status.c_str());
}

void SystemTray::update(void) {
if (_tray == nullptr) {
return;
}

if (_entry_showhide != nullptr) {
// check if window is open and adjust text and callback
const bool hidden {(SDL_GetWindowFlags(_main_window) & SDL_WINDOW_HIDDEN) > 0};
// TODO: cache state

if (hidden) {
SDL_SetTrayEntryLabel(_entry_showhide, "Show Tomato");
SDL_SetTrayEntryCallback(_entry_showhide,
+[](void* userdata, SDL_TrayEntry*){
SDL_ShowWindow(static_cast<SystemTray*>(userdata)->_main_window);
}
, this);
} else {
SDL_SetTrayEntryLabel(_entry_showhide, "Hide Tomato");
SDL_SetTrayEntryCallback(_entry_showhide,
+[](void* userdata, SDL_TrayEntry*){
SDL_HideWindow(static_cast<SystemTray*>(userdata)->_main_window);
}
, this);
}
}
}

24 changes: 24 additions & 0 deletions src/sys_tray.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
#pragma once

#include <SDL3/SDL.h>

#include <string>

class SystemTray {
SDL_Window* _main_window {nullptr};
SDL_Tray* _tray {nullptr};

SDL_TrayEntry* _entry_showhide {nullptr};
SDL_TrayEntry* _entry_status {nullptr};

public:
SystemTray(SDL_Window* main_window);
~SystemTray(void);

void setIcon(SDL_Surface* surf);
void setStatusText(const std::string& status);

// check if window is visible and adjust text
void update(void);
};

0 comments on commit 924c969

Please sign in to comment.