From 3190f16e20bfe03d83cead40d4dc220d619ec924 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jaakko=20Ker=C3=A4nen?= Date: Wed, 3 Feb 2021 14:48:42 +0200 Subject: [PATCH 1/1] XDG: Check XDG_CONFIG_HOME and the user's download directory Also added a build option to disable changing the user download directory within Lagrange, since that's set via XDG config. --- CMakeLists.txt | 4 +++ src/app.c | 78 ++++++++++++++++++++++++++++++-------------- src/ui/inputwidget.c | 1 + src/ui/util.c | 3 ++ 4 files changed, 62 insertions(+), 24 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index a3687e9c..095a279f 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -31,6 +31,7 @@ option (ENABLE_KERNING "Enable kerning in font renderer (slower)" ON) option (ENABLE_RESOURCE_EMBED "Embed resources inside the executable" OFF) option (ENABLE_WINDOWPOS_FIX "Set position after showing window (workaround for SDL bug)" OFF) option (ENABLE_IDLE_SLEEP "While idle, sleep in the main thread instead of waiting for events" ON) +option (ENABLE_DOWNLOAD_EDIT "Allow changing the Downloads directory" ON) include (BuildType.cmake) include (res/Embed.cmake) @@ -226,6 +227,9 @@ endif () if (ENABLE_IDLE_SLEEP) target_compile_definitions (app PUBLIC LAGRANGE_IDLE_SLEEP=1) endif () +if (ENABLE_DOWNLOAD_EDIT) + target_compile_definitions (app PUBLIC LAGRANGE_DOWNLOAD_EDIT=1) +endif () target_link_libraries (app PUBLIC the_Foundation::the_Foundation) target_link_libraries (app PUBLIC ${SDL2_LDFLAGS}) if (APPLE) diff --git a/src/app.c b/src/app.c index 10e6d4ee..195b3b43 100644 --- a/src/app.c +++ b/src/app.c @@ -83,17 +83,17 @@ static const char *dataDir_App_ = "~/AppData/Roaming/fi.skyjake.Lagrange"; #endif #if defined (iPlatformLinux) || defined (iPlatformOther) #define EMB_BIN "../../share/lagrange/resources.lgr" -static const char *dataDir_App_ = "~/.config/lagrange"; +static const char *defaultDataDir_App_ = "~/.config/lagrange"; #endif #if defined (LAGRANGE_EMB_BIN) /* specified in build config */ # undef EMB_BIN # define EMB_BIN LAGRANGE_EMB_BIN #endif #define EMB_BIN2 "../resources.lgr" /* fallback from build/executable dir */ -static const char *prefsFileName_App_ = "prefs.cfg"; -static const char *oldStateFileName_App_ = "state.binary"; -static const char *stateFileName_App_ = "state.lgr"; -static const char *downloadDir_App_ = "~/Downloads"; +static const char *prefsFileName_App_ = "prefs.cfg"; +static const char *oldStateFileName_App_ = "state.binary"; +static const char *stateFileName_App_ = "state.lgr"; +static const char *defaultDownloadDir_App_ = "~/Downloads"; static const int idleThreshold_App_ = 1000; /* ms */ @@ -213,14 +213,42 @@ static iString *serializePrefs_App_(const iApp *d) { return str; } +static const char *dataDir_App_(void) { +#if defined (iPlatformLinux) || defined (iPlatformOther) + const char *configHome = getenv("XDG_CONFIG_HOME"); + if (configHome) { + return concatPath_CStr(configHome, "lagrange"); + } +#endif + return defaultDataDir_App_; +} + +static const char *downloadDir_App_(void) { +#if defined (iPlatformLinux) || defined (iPlatformOther) + /* Parse user-dirs.dirs using the `xdg-user-dir` tool. */ + iProcess *proc = iClob(new_Process()); + setArguments_Process( + proc, iClob(newStringsCStr_StringList("/usr/bin/env", "xdg-user-dir", "DOWNLOAD", NULL))); + if (start_Process(proc)) { + iString *path = collect_String(newLocal_String(collect_Block( + readOutputUntilClosed_Process(proc)))); + trim_String(path); + if (!isEmpty_String(path)) { + return cstr_String(path); + } + } +#endif + return defaultDownloadDir_App_; +} + static const iString *prefsFileName_(void) { - return collect_String(concatCStr_Path(&iStringLiteral(dataDir_App_), prefsFileName_App_)); + return collectNewCStr_String(concatPath_CStr(dataDir_App_(), prefsFileName_App_)); } static void loadPrefs_App_(iApp *d) { iUnused(d); /* Create the data dir if it doesn't exist yet. */ - makeDirs_Path(collectNewCStr_String(dataDir_App_)); + makeDirs_Path(collectNewCStr_String(dataDir_App_())); iFile *f = new_File(prefsFileName_()); if (open_File(f, readOnly_FileMode | text_FileMode)) { iString *str = readString_File(f); @@ -267,8 +295,8 @@ static const char *magicTabDocument_App_ = "tabd"; static iBool loadState_App_(iApp *d) { iUnused(d); - const char *oldPath = concatPath_CStr(dataDir_App_, oldStateFileName_App_); - const char *path = concatPath_CStr(dataDir_App_, stateFileName_App_); + const char *oldPath = concatPath_CStr(dataDir_App_(), oldStateFileName_App_); + const char *path = concatPath_CStr(dataDir_App_(), stateFileName_App_); iFile *f = iClob(newCStr_File(fileExistsCStr_FileInfo(path) ? path : oldPath)); if (open_File(f, readOnly_FileMode)) { char magic[4]; @@ -323,7 +351,7 @@ iObjectList *listDocuments_App(void) { static void saveState_App_(const iApp *d) { iUnused(d); trimCache_App(); - iFile *f = newCStr_File(concatPath_CStr(dataDir_App_, stateFileName_App_)); + iFile *f = newCStr_File(concatPath_CStr(dataDir_App_(), stateFileName_App_)); if (open_File(f, writeOnly_FileMode)) { writeData_File(f, magicState_App_, 4); writeU32_File(f, latest_FileVersion); /* version */ @@ -348,7 +376,7 @@ static uint32_t checkAsleep_App_(uint32_t interval, void *param) { #endif static void init_App_(iApp *d, int argc, char **argv) { - const iBool isFirstRun = !fileExistsCStr_FileInfo(cleanedPath_CStr(dataDir_App_)); + const iBool isFirstRun = !fileExistsCStr_FileInfo(cleanedPath_CStr(dataDir_App_())); d->isFinishedLaunching = iFalse; d->launchCommands = new_StringList(); iZap(d->lastDropTime); @@ -385,12 +413,12 @@ static void init_App_(iApp *d, int argc, char **argv) { } #endif init_Prefs(&d->prefs); - setCStr_String(&d->prefs.downloadDir, downloadDir_App_); + setCStr_String(&d->prefs.downloadDir, downloadDir_App_()); d->isRunning = iFalse; d->window = NULL; set_Atomic(&d->pendingRefresh, iFalse); d->mimehooks = new_MimeHooks(); - d->certs = new_GmCerts(dataDir_App_); + d->certs = new_GmCerts(dataDir_App_()); d->visited = new_Visited(); d->bookmarks = new_Bookmarks(); d->tabEnum = 0; /* generates unique IDs for tab pages */ @@ -405,10 +433,10 @@ static void init_App_(iApp *d, int argc, char **argv) { #endif init_Keys(); loadPrefs_App_(d); - load_Keys(dataDir_App_); - load_Visited(d->visited, dataDir_App_); - load_Bookmarks(d->bookmarks, dataDir_App_); - load_MimeHooks(d->mimehooks, dataDir_App_); + load_Keys(dataDir_App_()); + load_Visited(d->visited, dataDir_App_()); + load_Bookmarks(d->bookmarks, dataDir_App_()); + load_MimeHooks(d->mimehooks, dataDir_App_()); if (isFirstRun) { /* Create the default bookmarks for a quick start. */ add_Bookmarks(d->bookmarks, @@ -434,7 +462,7 @@ static void init_App_(iApp *d, int argc, char **argv) { } #endif d->window = new_Window(d->initialWindowRect); - init_Feeds(dataDir_App_); + init_Feeds(dataDir_App_()); /* Widget state init. */ processEvents_App(postedEventsOnly_AppEventMode); if (!loadState_App_(d)) { @@ -469,13 +497,13 @@ static void init_App_(iApp *d, int argc, char **argv) { static void deinit_App(iApp *d) { saveState_App_(d); deinit_Feeds(); - save_Keys(dataDir_App_); + save_Keys(dataDir_App_()); deinit_Keys(); savePrefs_App_(d); deinit_Prefs(&d->prefs); - save_Bookmarks(d->bookmarks, dataDir_App_); + save_Bookmarks(d->bookmarks, dataDir_App_()); delete_Bookmarks(d->bookmarks); - save_Visited(d->visited, dataDir_App_); + save_Visited(d->visited, dataDir_App_()); delete_Visited(d->visited); delete_GmCerts(d->certs); save_MimeHooks(d->mimehooks); @@ -494,7 +522,7 @@ const iString *execPath_App(void) { } const iString *dataDir_App(void) { - return collect_String(cleanedCStr_Path(dataDir_App_)); + return collect_String(cleanedCStr_Path(dataDir_App_())); } const iString *downloadDir_App(void) { @@ -854,8 +882,10 @@ static iBool handlePrefsCommands_(iWidget *d, const char *cmd) { if (equal_Command(cmd, "prefs.dismiss") || equal_Command(cmd, "preferences")) { setUiScale_Window(get_Window(), toFloat_String(text_InputWidget(findChild_Widget(d, "prefs.uiscale")))); +#if defined (LAGRANGE_DOWNLOAD_EDIT) postCommandf_App("downloads path:%s", cstr_String(text_InputWidget(findChild_Widget(d, "prefs.downloads")))); +#endif postCommandf_App("window.retain arg:%d", isSelected_Widget(findChild_Widget(d, "prefs.retainwindow"))); postCommandf_App("smoothscroll arg:%d", @@ -1449,7 +1479,7 @@ iBool handleCommand_App(const char *cmd) { return iTrue; } else if (equal_Command(cmd, "bookmarks.changed")) { - save_Bookmarks(d->bookmarks, dataDir_App_); + save_Bookmarks(d->bookmarks, dataDir_App_()); return iFalse; } else if (equal_Command(cmd, "feeds.refresh")) { @@ -1468,7 +1498,7 @@ iBool handleCommand_App(const char *cmd) { return iFalse; } else if (equal_Command(cmd, "visited.changed")) { - save_Visited(d->visited, dataDir_App_); + save_Visited(d->visited, dataDir_App_()); return iFalse; } else if (equal_Command(cmd, "ident.new")) { diff --git a/src/ui/inputwidget.c b/src/ui/inputwidget.c index 3f799e3c..1674040b 100644 --- a/src/ui/inputwidget.c +++ b/src/ui/inputwidget.c @@ -223,6 +223,7 @@ static void updateBuffered_InputWidget_(iInputWidget *d) { } void setText_InputWidget(iInputWidget *d, const iString *text) { + if (!d) return; if (d->inFlags & isUrl_InputWidgetFlag) { /* If user wants URLs encoded, also Punycode the domain. */ if (!prefs_App()->decodeUserVisibleURLs) { diff --git a/src/ui/util.c b/src/ui/util.c index 4d5ed916..d64a93b6 100644 --- a/src/ui/util.c +++ b/src/ui/util.c @@ -1023,6 +1023,7 @@ static void makeTwoColumnHeading_(const char *title, iWidget *headings, iWidget } static void expandInputFieldWidth_(iInputWidget *input) { + if (!input) return; iWidget *page = as_Widget(input)->parent->parent->parent->parent; /* tabs > page > values > input */ as_Widget(input)->rect.size.x = right_Rect(bounds_Widget(page)) - left_Rect(bounds_Widget(constAs_Widget(input))); @@ -1056,8 +1057,10 @@ iWidget *makePreferences_Widget(void) { iWidget *headings, *values; /* General preferences. */ { appendTwoColumnPage_(tabs, "General", '1', &headings, &values); +#if defined (LAGRANGE_DOWNLOAD_EDIT) addChild_Widget(headings, iClob(makeHeading_Widget("Downloads folder:"))); setId_Widget(addChild_Widget(values, iClob(new_InputWidget(0))), "prefs.downloads"); +#endif addChild_Widget(headings, iClob(makeHeading_Widget("Show URL on hover:"))); addChild_Widget(values, iClob(makeToggle_Widget("prefs.hoverlink"))); addChild_Widget(headings, iClob(makeHeading_Widget("Smooth scrolling:"))); -- 2.34.1