windows integration

Signed-off-by: Hans Dijkema <hans@dijkewijk.nl>
This commit is contained in:
2025-11-26 13:56:19 +01:00
parent bf62ec97dc
commit 5023b63a7e
10 changed files with 440 additions and 56 deletions

View File

@@ -11,9 +11,9 @@ add_executable(yellownotes main.cpp
gtk-imports.c
yellownotes.h yellownotes.cpp
tr.h tr.cpp
win32gtkdownloader.h win32gtkdownloader.cpp)
win32gtkdownloader.h win32gtkdownloader.cpp
utils/whereami.c utils/whereami.h
exe_path.h exe_path.cpp)
info_over_me.h info_over_me.cpp)
include(GNUInstallDirs)
install(TARGETS yellownotes

View File

@@ -1,20 +0,0 @@
#include "exe_path.h"
#include "utils/whereami.h"
#include <iostream>
std::string WhereAmI::containing_folder()
{
int len = wai_getExecutablePath(NULL, 0, NULL);
char *path = static_cast<char *>(malloc(len + 1));
wai_getExecutablePath(path, len, NULL);
path[len] = '\0';
std::string p(path);
std::cout << p << std::endl;
return p;
}
WhereAmI::WhereAmI() {}

View File

@@ -1,14 +0,0 @@
#ifndef EXE_PATH_H
#define EXE_PATH_H
#include <string>
class WhereAmI
{
public:
std::string containing_folder();
public:
WhereAmI();
};
#endif // EXE_PATH_H

View File

@@ -74,6 +74,8 @@ typedef void GtkGrid;
typedef void GtkColorButton;
typedef void GtkColorChooser;
typedef void GtkSpinButton;
typedef void GdkMonitor;
typedef void GdkScreen;
typedef int gboolean;
typedef int gint;
@@ -142,14 +144,14 @@ typedef enum {
PANGO_ELLIPSIZE_END = 3
} PangoEllipsizeMode;
struct GdkRectangle {
typedef struct _GdkRectangle {
int x;
int y;
int width;
int height;
};
} GdkRectangle;
typedef struct GdkRectangle GtkAllocation;
typedef struct _GdkRectangle GtkAllocation;
#define G_VALUE_INIT { 0, { { 0 } } }
@@ -570,6 +572,14 @@ typedef struct _GdkEventVisibility
GdkVisibilityState state;
} GdkEventVisibility;
typedef struct _GList {
gpointer data;
gpointer next;
gpointer prev;
} GList;
typedef void GListModel;
#define G_TYPE_FUNDAMENTAL_SHIFT (2)
#define G_TYPE_MAKE_FUNDAMENTAL(x) ((GType) ((x) << G_TYPE_FUNDAMENTAL_SHIFT))
#define G_TYPE_INT G_TYPE_MAKE_FUNDAMENTAL (6)
@@ -693,6 +703,15 @@ DECL(GtkWidget*, gtk_dialog_get_content_area, (GtkDialog* dialog ))
DECL(gboolean, gtk_combo_box_set_active_id, ( GtkComboBox* combo_box, const gchar* active_id ))
DECL(const gchar*, gtk_combo_box_get_active_id, (GtkComboBox* combo_box))
// Gdk Monitor/Screen
DECL(GdkDisplay*, gdk_display_get_default, (void))
DECL(int, gdk_display_get_n_monitors, (GdkDisplay* display))
DECL(GdkMonitor*, gdk_display_get_monitor, (GdkDisplay* display, int monitor_num))
DECL(void, gdk_monitor_get_geometry, (GdkMonitor* monitor, GdkRectangle* geometry))
DECL(GList*, gdk_screen_get_window_stack, (GdkScreen* screen))
DECL(GdkScreen*, gdk_screen_get_default, (void))
// GObject / GValue
DECL(void, g_object_unref, (GObject* object))
DECL(void, g_object_ref, (GObject* object))

109
info_over_me.cpp Normal file
View File

@@ -0,0 +1,109 @@
#include "info_over_me.h"
#include "utils/whereami.h"
#include <iostream>
#ifdef __linux
#include <unistd.h>
#endif
#ifdef _WIN32
#include <windows.h>
#endif
extern "C" {
#include "gtk-imports.h"
}
#include <list>
std::string InfoOverMe::containingFolder()
{
int len = wai_getExecutablePath(NULL, 0, NULL);
char *path = static_cast<char *>(malloc(len + 1));
wai_getExecutablePath(path, len, NULL);
path[len] = '\0';
std::string p(path);
std::cout << p << std::endl;
return p;
}
std::string InfoOverMe::myHostname()
{
char buf[10240];
#ifdef __linux
int r = gethostname(buf, 10240);
#endif
#ifdef _WIN32
DWORD size = 10240;
bool r = GetComputerNameA(buf, &size);
buf[size] = '\0';
if (!r) { sprintf(buf, "unknown"); }
#endif
std::string name(buf);
return name;
}
std::string InfoOverMe::myOsHostname()
{
std::string os;
#ifdef __linux
os = "linux";
#else
#ifdef _WIN32
os = "windows";
#else
os = "unknown";
#endif
#endif
return os + "_" + myHostname();
}
std::string InfoOverMe::myId()
{
std::list<GdkRectangle> l;
GdkDisplay *d = gdk_display_get_default();
int n = gdk_display_get_n_monitors(d);
int i;
for(i = 0; i < n; i++) {
GdkMonitor *m = gdk_display_get_monitor(d, i);
GdkRectangle r;
gdk_monitor_get_geometry(m, &r);
l.push_back(r);
//std::cout << r.width << ", " << r.height << ", x = " << r.x << ", y = " << r.y << std::endl;
}
auto compare = [](const GdkRectangle &a, const GdkRectangle &b) {
if (a.x < b.x) {
return true;
} else if (a.x > b. x) {
return false;
} else if (a.y < b.y) {
return true;
} else {
return false;
}
};
l.sort(compare);
std::list<GdkRectangle>::iterator it;
std::string monitor_id;
std::string sep = "";
for(it = l.begin(); it != l.end(); it++) {
char buf[200];
const GdkRectangle &r = *it;
sprintf(buf, "%d-%d-%d-%d", r.x, r.y, r.width, r.height);
std::string geom(buf);
monitor_id += sep;
monitor_id += geom;
sep = "-";
}
monitor_id = myOsHostname() + "/" + monitor_id;
return monitor_id;
}
InfoOverMe::InfoOverMe() {}

20
info_over_me.h Normal file
View File

@@ -0,0 +1,20 @@
#ifndef INFO_OVER_ME_H
#define INFO_OVER_ME_H
#include <string>
class InfoOverMe
{
public:
std::string containingFolder();
public:
std::string myHostname();
std::string myOsHostname();
std::string myId();
public:
InfoOverMe();
};
#endif // INFO_OVER_ME_H

View File

@@ -6,7 +6,7 @@ extern "C" {
}
#include "yellownotes.h"
#include "exe_path.h"
#include "info_over_me.h"
SIGNAL(YellowNotes, on_tray_activate, popupTrayMenu)
@@ -23,11 +23,13 @@ static void activate (GtkApplication* app, gpointer user_data)
int main(int argc, char **argv)
{
GtkLoader l;
WhereAmI w;
InfoOverMe w;
std::cout << w.myOsHostname() << std::endl;
srand(time(NULL)); // seed with current time
std::string my_path = w.containing_folder();
std::string my_path = w.containingFolder();
try {
l.loadGtk();

1
tr.cpp
View File

@@ -95,6 +95,7 @@ tr::tr()
nl("Grey", "Grijs");
nl("Font size:", "Lettertype Grootte:");
nl("Actual Font Size in Note", "Werkelijke lettertype grootte in de notitie");
nl("Reorder Notes", "Notities opnieuw ordenen");
_lang = "en";
}

View File

@@ -13,6 +13,7 @@
#ifdef _WIN32
#include <windows.h>
#include <shobjidl.h>
#endif
#include <string.h>
@@ -21,7 +22,9 @@ extern "C" {
}
#include "tr.h"
#include "info_over_me.h"
#include <functional>
#include <sstream>
#include <math.h>
static void trim(std::string &s) {
@@ -34,6 +37,17 @@ static void trim(std::string &s) {
s = s.substr(start, end - start + 1);
}
class StoredCoords
{
public:
bool hidden;
int x;
int y;
int width;
int height;
std::string os_host;
};
class YellowNote
{
@@ -65,6 +79,8 @@ private:
std::string _note;
std::string _title;
std::list<StoredCoords> _stored_coords;
bool _hidden;
bool _hidden_loaded;
@@ -143,6 +159,7 @@ public:
bool textSaveTimeout();
bool windowPresented(void *sender, GdkEventVisibility *evt);
void showNote(GtkWidget *sender);
void moveTo(int x, int y);
public:
std::string title();
@@ -232,10 +249,12 @@ SIGNAL(YellowNotes, on_to_back, notesToDesktop);
SIGNAL(YellowNotes, on_reload, reloadNotes);
SIGNAL(YellowNotes, on_setup, setup);
SIGNAL(YellowNotes, on_quit, quit)
SIGNAL(YellowNotes, on_reorder, reOrder);
SIGNAL(YellowNotes, on_hide_toplevel, topLevelHidden)
SIGNAL(YellowNotes, on_setup_ok, setupClose);
SIGNAL(YellowNotes, on_setup_close, setupCancel);
BSIGNAL2(YellowNotes, on_setup_del, setupDel, void);
SIGNAL(YellowNotes, on_monitors_changed, monitorsChanged);
std::string YellowNotes::imageFile(const char *name)
@@ -326,6 +345,11 @@ void YellowNotes::updateWidgetCss(GtkWidget *w, ColorType_t col)
set_style(w);
}
GtkWidget *YellowNotes::getWindow()
{
return topLevel();
}
std::string YellowNotes::getFgColor(ColorType_t type)
{
char buf[100];
@@ -496,6 +520,7 @@ void YellowNotes::popupTrayMenu(void *sender)
GtkWidget *sep1 = gtk_separator_menu_item_new();
GtkMenuItem *setup = gtk_menu_item_new_with_label(_("Setup"));
GtkMenuItem *reorder = gtk_menu_item_new_with_label(_("Reorder Notes"));
GtkMenuItem *quit = gtk_menu_item_new_with_label(_("Quit"));
gtk_menu_shell_append(tray_menu, new_yellow);
@@ -512,6 +537,7 @@ void YellowNotes::popupTrayMenu(void *sender)
gtk_menu_shell_append(tray_menu, sep1);
gtk_menu_shell_append(tray_menu, setup);
gtk_menu_shell_append(tray_menu, reorder);
gtk_menu_shell_append(tray_menu, quit);
gtk_widget_show_all(tray_menu);
@@ -520,6 +546,7 @@ void YellowNotes::popupTrayMenu(void *sender)
g_signal_connect(notes_to_back, "activate", on_to_back, this);
g_signal_connect(reload_notes, "activate", on_reload, this);
g_signal_connect(setup, "activate", on_setup, this);
g_signal_connect(reorder, "activate", on_reorder, this);
g_signal_connect(quit, "activate", on_quit, this);
w_it = hidden.begin();
it = h_notes.begin();
@@ -811,6 +838,22 @@ void YellowNotes::setup(void *sender)
gtk_widget_show_all(dlg);
}
void YellowNotes::reOrder(void *sender)
{
int x = 50;
int y = 50;
std::list<YellowNote *>::iterator it;
for(it = _notes.begin(); it != _notes.end(); it++, x += 25, y += 25) {
(*it)->moveTo(x, y);
}
}
void YellowNotes::monitorsChanged(void *sender)
{
this->reloadNotes(sender);
}
void YellowNotes::reloadNotes(void *sender)
{
std::list<YellowNote *>::const_iterator it = _notes.begin();
@@ -911,6 +954,87 @@ void YellowNotes::topLevelHidden(GtkWidget *sender)
g_timeout_add(500, show_notes_timed, this);
}
void YellowNotes::checkMonitors()
{
auto compare = [](const Geom_t &a, const Geom_t &b) {
if (a.x < b.x) {
return true;
} else if (a.x > b. x) {
return false;
} else if (a.y < b.y) {
return true;
} else {
return false;
}
};
GdkDisplay *d = gdk_display_get_default();
int n = gdk_display_get_n_monitors(d);
if (_monitors.empty()) {
int i;
for(i = 0; i < n; i++) {
GdkMonitor *m = gdk_display_get_monitor(d, i);
GdkRectangle r;
gdk_monitor_get_geometry(m, &r);
Geom_t g;
g.x = r.x;
g.y = r.y;
g.width = r.width;
g.height = r.height;
_monitors.push_back(g);
}
_monitors.sort(compare);
} else {
if (n != _monitors.size()) {
_monitors.clear();
checkMonitors();
monitorsChanged(nullptr);
} else {
std::list<Geom_t> l;
int i;
for(i = 0; i < n; i++) {
GdkMonitor *m = gdk_display_get_monitor(d, i);
GdkRectangle r;
gdk_monitor_get_geometry(m, &r);
Geom_t g;
g.x = r.x;
g.y = r.y;
g.width = r.width;
g.height = r.height;
l.push_back(g);
}
l.sort(compare);
std::list<Geom_t>::iterator m_it = _monitors.begin();
std::list<Geom_t>::iterator l_it = l.begin();
while(l_it != l.end()) {
Geom_t g_l = *l_it;
Geom_t g_m = *m_it;
if (g_l.x != g_m.x || g_l.y != g_m.y || g_l.width != g_m.width || g_l.height != g_m.height) {
_monitors.clear();
checkMonitors();
monitorsChanged(nullptr);
}
l_it++;
m_it++;
}
}
}
}
static YellowNotes *_the_notes = nullptr;
gboolean monitor_monitors(void *data)
{
YellowNotes *n = reinterpret_cast<YellowNotes *>(data);
if (_the_notes == nullptr) {
return false;
} else {
n->checkMonitors();
return true;
}
}
GtkWindow *YellowNotes::topLevel()
{
if (_toplevel == nullptr) {
@@ -927,11 +1051,14 @@ YellowNotes::YellowNotes(void *app)
_tray_menu = nullptr;
_font_size = 15;
_toplevel = nullptr;
_the_notes = this;
g_timeout_add(1000, monitor_monitors, this); // Beware monitor_monitors checks _the_notes.
loadConfig();
}
YellowNotes::~YellowNotes()
{
_the_notes = nullptr;
if (_tray_menu) { gtk_widget_destroy(reinterpret_cast<GtkMenu *>(_tray_menu)); }
clearNotes();
gtk_widget_destroy(_toplevel);
@@ -1228,6 +1355,13 @@ void YellowNote::showNote(GtkWidget *sender)
show();
}
void YellowNote::moveTo(int x, int y)
{
_x = x;
_y = y;
updatePosition();
}
void YellowNote::setLoaded()
{
_pos_loaded = true;
@@ -1299,12 +1433,20 @@ void YellowNote::toFront()
}
}
void YellowNote::toDesktop()
{
#ifdef __linux
gtk_window_set_type_hint(_note_widget, GdkWindowTypeHint::GDK_WINDOW_TYPE_HINT_DESKTOP);
#endif
#ifdef _WIN32
GdkWindow *notes_win = gtk_widget_get_window(_notes->getWindow());
HWND nw = gdk_win32_window_get_handle(notes_win);
SetWindowPos(nw, HWND_BOTTOM, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE | SWP_NOACTIVATE);
GdkWindow *win = gtk_widget_get_window(_note_widget);
HWND w = gdk_win32_window_get_handle(win);
SetWindowPos(w, HWND_BOTTOM, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE | SWP_NOACTIVATE);
#endif
}
void YellowNote::fromDesktop()
@@ -1655,7 +1797,7 @@ bool YellowNote::moving(GtkWidget *sender, GdkEventMotion *evt)
return false;
}
#define YELLOWNOTE_VERSION 2
#define YELLOWNOTE_VERSION 3
void YellowNote::load()
{
@@ -1678,6 +1820,68 @@ void YellowNote::load()
std::string title;
bool title_only;
InfoOverMe info;
std::string my_name = info.myId();
auto readKind = [my_name, this](std::string line, std::function<void (const std::string &os_host, int val)> f) {
// Split line in parts.
std::istringstream inp(line);
std::string part;
bool found = false;
while(std::getline(inp, part, ',')) {
std::string os_host;
int val;
int idx;
idx = part.find(":");
if (idx >= 0) {
os_host = part.substr(0, idx);
std::string s = part.substr(idx + 1);
val = atoi(s.c_str());
f(os_host,val);
if (os_host == my_name) { found = true; }
}
}
return found;
};
auto getStoredCoord = [this](const std::string &os_host, bool &created) {
std::list<StoredCoords>::iterator it = _stored_coords.begin();
while(it != _stored_coords.end() && it->os_host != os_host) {
it++;
}
if (it == _stored_coords.end()) {
StoredCoords c;
c.os_host = os_host;
_stored_coords.push_back(c);
StoredCoords *r = &(_stored_coords.back());
created = true;
return r;
} else {
StoredCoords *r = &(*it);
created = false;
return r;
}
};
auto setStoredCoordVar = [this, getStoredCoord, readKind](std::string line, std::function<void(StoredCoords *c, int v)> f) {
auto setter = [f, this, getStoredCoord](const std::string &os_name, int val) {
bool created;
StoredCoords *r = getStoredCoord(os_name, created);
f(r, val);
};
readKind(line, setter);
};
auto readLine = [](FILE *f) {
char buf[10240];
fgets(buf, 10240, f);
std::string l(buf);
trim(l);
return l;
};
_stored_coords.clear();
size_t s = 0;
if (std::filesystem::is_regular_file(p)) {
s = std::filesystem::file_size(p);
@@ -1687,11 +1891,36 @@ void YellowNote::load()
if (f) {
int version = readInt(f, -1);
hidden = readInt(f, -1);
x = readInt(f, 200);
y = readInt(f, 200);
width = readInt(f, 300);
height = readInt(f, 200);
if (version <= 2) {
hidden = readInt(f, -1);
x = readInt(f, 200);
y = readInt(f, 200);
width = readInt(f, 300);
height = readInt(f, 200);
} else {
// fill in the dots.
setStoredCoordVar(readLine(f), [](StoredCoords *c, int val) { c->hidden = val; });
setStoredCoordVar(readLine(f), [](StoredCoords *c, int val) { c->x = val; });
setStoredCoordVar(readLine(f), [](StoredCoords *c, int val) { c->y = val; });
setStoredCoordVar(readLine(f), [](StoredCoords *c, int val) { c->width = val; });
setStoredCoordVar(readLine(f), [](StoredCoords *c, int val) { c->height = val; });
bool created;
StoredCoords *r = getStoredCoord(my_name, created);
if (created) {
r->hidden = false;
r->x = 100;
r->y = 100;
r->width = 300;
r->height = 200;
}
hidden = r->hidden;
x = r->x;
y = r->y;
width = r->width;
height = r->height;
}
int color;
color = readInt(f, ColorType_t::YELLOW);
@@ -1751,15 +1980,43 @@ void YellowNote::save()
return;
}
InfoOverMe info;
std::string my_name = info.myId();
auto storeKind = [my_name, this](int val, std::function<int (const StoredCoords &)> f) {
std::string line("");
std::list<StoredCoords>::iterator it;
std::string comma("");
bool stored = false;
for(it = _stored_coords.begin(); it != _stored_coords.end(); it++) {
const StoredCoords &c = *it;
int num = (my_name == c.os_host) ? val : f(c);
if (my_name == c.os_host) { stored = true; }
char buf[100];
sprintf(buf, "%d", num);
line += comma + c.os_host + ":" + buf;
comma = ",";
}
if (!stored) {
char buf[100];
sprintf(buf, "%d", val);
line += comma + my_name + ":" + buf;
}
return line;
};
std::filesystem::path p(_filename);
FILE *f = fopen(_filename.c_str(), "wt");
if (f) {
fprintf(f, "%d\n", YELLOWNOTE_VERSION);
fprintf(f, "%d\n", _hidden);
fprintf(f, "%d\n", _x);
fprintf(f, "%d\n", _y);
fprintf(f, "%d\n", _width);
fprintf(f, "%d\n", _height);
fprintf(f, "%s\n", storeKind(_hidden, [](const StoredCoords &c) { return c.hidden; }).c_str());
fprintf(f, "%s\n", storeKind(_x, [](const StoredCoords &c) { return c.x; }).c_str());
fprintf(f, "%s\n", storeKind(_y, [](const StoredCoords &c) { return c.y; }).c_str());
fprintf(f, "%s\n", storeKind(_width, [](const StoredCoords &c) { return c.width; }).c_str());
fprintf(f, "%s\n", storeKind(_height, [](const StoredCoords &c) { return c.height; }).c_str());
fprintf(f, "%d\n", _color);
fprintf(f, "%d\n", _title_only);
fprintf(f, "%s\n", _title.c_str());

View File

@@ -25,6 +25,11 @@ typedef enum {
LAST = GREY
} ColorType_t;
class Geom_t {
public:
int x, y, width, height;
};
class YellowNotes
{
private:
@@ -34,12 +39,13 @@ private:
void *_langs;
std::list<SettingContainer *> _settings_containers;
std::list<YellowNote *> _notes;
int _font_size;
GtkWindow *_toplevel;
std::unordered_map<std::string, std::string> _cfg;
std::list<Geom_t> _monitors;
private:
void loadConfig();
void saveConfig();
@@ -66,13 +72,16 @@ public:
void notesToDesktop(void *sender);
void notesFromDesktop(void *sender);
void reloadNotes(void *sender);
void monitorsChanged(void *sender);
void quit(void *sender);
void topLevelHidden(GtkWidget *sender);
void setup(void *sender);
void reOrder(void *sender);
void setupClose(GtkWidget *sender);
void setupCancel(GtkWidget *sender);
bool setupDel(GtkWidget *sender, void *evt);
void remove(YellowNote *n);
void checkMonitors();
public:
std::string currentLang();
@@ -86,6 +95,7 @@ public:
std::string fromRGBA(const GdkRGBA &rgba);
void toRGBA(const std::string &col, GdkRGBA &rgba);
void updateWidgetCss(GtkWidget *w, ColorType_t col);
GtkWidget *getWindow();
public:
YellowNotes(void *app);