diff --git a/.gitignore b/.gitignore index 90b3ebb..ba36e26 100644 --- a/.gitignore +++ b/.gitignore @@ -10,6 +10,10 @@ build/ .vscode +tags +types_c.taghl +*~ + # Prerequisites *.d diff --git a/CMakeLists.txt b/CMakeLists.txt index 78672fa..58e5c45 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -82,11 +82,13 @@ set(CPACK_NSIS_MUI_ICON ${CMAKE_CURRENT_SOURCE_DIR}/icon.ico) set(CPACK_NSIS_MUI_UNIICON ${CMAKE_CURRENT_SOURCE_DIR}/icon.ico) set(CPACK_NSIS_INSTALLED_ICON_NAME ${CMAKE_CURRENT_SOURCE_DIR}/icon.ico) set(CPACK_NSIS_EXTRA_INSTALL_COMMANDS " - WriteRegExpandStr HKLM 'Software\\\\Microsoft\\\\Windows\\\\CurrentVersion\\\\Run' 'lwp' '\$INSTDIR\\\\lwp.exe' + WriteRegExpandStr HKLM 'Software\\\\Microsoft\\\\Windows\\\\CurrentVersion\\\\Run' 'lwp' '\$INSTDIR\\\\lwp.exe' Exec '\$INSTDIR\\\\lwp.exe' + CreateShortCut \\\"$DESKTOP\\\\Layered WallPaper.lnk\\\" \\\"$INSTDIR\\\\lwp.exe\\\" ") set(CPACK_NSIS_EXTRA_UNINSTALL_COMMANDS " DeleteRegValue HKLM 'Software\\\\Microsoft\\\\Windows\\\\CurrentVersion\\\\Run' 'lwp' + Delete \\\"$DESKTOP\\\\Layered WallPaper.lnk\\\" ") set(CPACK_PACKAGE_NAME "Layered WallPaper") set(CPACK_PACKAGE_VENDOR "Jakub Szczerbinski") diff --git a/src/common.h b/src/common.h index e17526b..bd07c8b 100644 --- a/src/common.h +++ b/src/common.h @@ -1,17 +1,24 @@ #ifndef COMMON_H #define COMMON_H +#include "platform_guard.h" + #ifdef __LINUX #include #else -#include +#include +#include #endif -#define MONITOR_NAME_MAX 100 +#define MONITOR_NAME_MAX 128 #define WALLPAPER_NAME_MAX 100 #define DEFAULT_LINUX_PREFIX "/usr/local" +#define LOG_ERROR 0 +#define LOG_INFO 1 +#define LOG_WARNING 2 + typedef struct { int x; @@ -32,7 +39,7 @@ typedef struct int repeatX; int repeatY; int layersCount; - LayerConfig *layerConfigs; + LayerConfig* layerConfigs; } WallpaperConfig; typedef struct @@ -46,22 +53,27 @@ typedef struct typedef struct { int loaded; + int active; char wlpName[WALLPAPER_NAME_MAX]; Bounds wlpBounds; } MonitorConfig; typedef struct { + char displayName[MONITOR_NAME_MAX]; char name[MONITOR_NAME_MAX]; - Bounds bounds; + Bounds pixelBounds; + Bounds clientBounds; + Bounds virtualBounds; MonitorConfig config; } MonitorInfo; typedef struct { - int drawOnRootWindow; int targetFps; char renderQuality[8]; + int unfocusedComeback; + int wndTargetPoint; } AppConfig; // @@ -72,12 +84,12 @@ typedef struct #define APP_DIR_SHARE 1 #define APP_DIR_USER_SETTINGS 2 -void getAppDir(char *buff, int type); +void getAppDir(char* buff, int type); -void getMonitorCfgPath(char *buff, const char *name); -void getWlpCfgPath(char *buff, const char *dirPath); -void getAppCfgPath(char *buff); -void getLogPath(char *buff); +void getMonitorCfgPath(char* buff, const char* name); +void getWlpCfgPath(char* buff, const char* dirPath); +void getAppCfgPath(char* buff); +void getLogPath(char* buff); void createUserDirs(); @@ -85,24 +97,31 @@ void createUserDirs(); // monitorScanner.c // -MonitorInfo *scanMonitors(int *count); +MonitorInfo* scanMonitors(int* count); // // wallpaperScanner.c // -WallpaperInfo *scanWallpapers(int *count); +WallpaperInfo* scanWallpapers(int* count); // // config.c // -void saveMonitorConfig(const char *name, MonitorConfig *mc); -int loadMonitorConfig(const char *name, MonitorConfig *mc); +void saveMonitorConfig(const char* name, MonitorConfig* mc); +int loadMonitorConfig(const char* name, MonitorConfig* mc); + +int loadAppConfig(AppConfig* ac); +void saveAppConfig(AppConfig* ac); -int loadAppConfig(AppConfig *ac); -void saveAppConfig(AppConfig *ac); +int loadWallpaperConfig(const char* dirName, WallpaperConfig* wc); -int loadWallpaperConfig(const char *dirName, WallpaperConfig *wc); +// +// debug.c +// +void clearlog(); +void printlog(int type, const char* str, ...); +char* readLogFile(); #endif diff --git a/src/common/config.c b/src/common/config.c index 292c327..8f5d6c7 100644 --- a/src/common/config.c +++ b/src/common/config.c @@ -7,7 +7,7 @@ #define CONFIG_DEFAULT 0 #define CONFIG_USER 1 -static void generateEmptyMonitorConfig(MonitorConfig *mc) +static void generateEmptyMonitorConfig(MonitorConfig* mc) { sprintf(mc->wlpName, ""); mc->wlpBounds.x = 0; @@ -16,7 +16,7 @@ static void generateEmptyMonitorConfig(MonitorConfig *mc) mc->wlpBounds.h = 1080; } -void saveMonitorConfig(const char *name, MonitorConfig *mc) +void saveMonitorConfig(const char* name, MonitorConfig* mc) { config_t cfg; config_setting_t *root, *setting; @@ -24,6 +24,9 @@ void saveMonitorConfig(const char *name, MonitorConfig *mc) config_init(&cfg); root = config_root_setting(&cfg); + setting = config_setting_add(root, "active", CONFIG_TYPE_INT); + config_setting_set_int(setting, mc->active); + setting = config_setting_add(root, "wlpName", CONFIG_TYPE_STRING); config_setting_set_string(setting, mc->wlpName); @@ -48,7 +51,7 @@ void saveMonitorConfig(const char *name, MonitorConfig *mc) config_destroy(&cfg); } -int loadMonitorConfig(const char *name, MonitorConfig *mc) +int loadMonitorConfig(const char* name, MonitorConfig* mc) { mc->loaded = 0; @@ -69,6 +72,12 @@ int loadMonitorConfig(const char *name, MonitorConfig *mc) if (config_read_file(&cfg, path) == CONFIG_FALSE) return 0; root = config_root_setting(&cfg); + setting = config_setting_get_member(root, "active"); + if (!setting) + mc->active = 1; + else + mc->active = config_setting_get_int(setting); + setting = config_setting_get_member(root, "wlpName"); strcpy(mc->wlpName, config_setting_get_string(setting)); @@ -87,16 +96,15 @@ int loadMonitorConfig(const char *name, MonitorConfig *mc) return 1; } -static void useDefaultAppCfg(AppConfig *ac) +static void useDefaultAppCfg(AppConfig* ac) { -#ifdef __LINUX - ac->drawOnRootWindow = 0; -#endif ac->targetFps = 60; strcpy(ac->renderQuality, "best"); + ac->wndTargetPoint = 0; + ac->unfocusedComeback = 1; } -void saveAppConfig(AppConfig *ac) +void saveAppConfig(AppConfig* ac) { config_t cfg; config_setting_t *root, *setting; @@ -104,14 +112,14 @@ void saveAppConfig(AppConfig *ac) config_init(&cfg); root = config_root_setting(&cfg); -#ifdef __LINUX - setting = config_setting_add(root, "draw_on_rootwindow", CONFIG_TYPE_INT); - config_setting_set_int(setting, ac->drawOnRootWindow); -#endif setting = config_setting_add(root, "target_fps", CONFIG_TYPE_INT); config_setting_set_int(setting, ac->targetFps); setting = config_setting_add(root, "render_quality", CONFIG_TYPE_STRING); config_setting_set_string(setting, ac->renderQuality); + setting = config_setting_add(root, "unfocused_comeback", CONFIG_TYPE_INT); + config_setting_set_int(setting, ac->unfocusedComeback); + setting = config_setting_add(root, "wnd_target_point", CONFIG_TYPE_INT); + config_setting_set_int(setting, ac->wndTargetPoint); char path[PATH_MAX]; getAppCfgPath(path); @@ -125,7 +133,7 @@ void saveAppConfig(AppConfig *ac) config_destroy(&cfg); } -int loadAppConfig(AppConfig *ac) +int loadAppConfig(AppConfig* ac) { config_t cfg; config_setting_t *root, *setting; @@ -141,21 +149,35 @@ int loadAppConfig(AppConfig *ac) } root = config_root_setting(&cfg); -#ifdef __LINUX - setting = config_setting_get_member(root, "draw_on_rootwindow"); - ac->drawOnRootWindow = config_setting_get_int(setting); -#endif - setting = config_setting_get_member(root, "target_fps"); - ac->targetFps = config_setting_get_int(setting); - setting = config_setting_get_member(root, "render_quality"); - strcpy(ac->renderQuality, config_setting_get_string(setting)); + setting = config_setting_get_member(root, "target_fps"); + if (setting == NULL) + ac->targetFps = 60; + else + ac->targetFps = config_setting_get_int(setting); + + setting = config_setting_get_member(root, "render_quality"); + if (setting == NULL) + strcpy(ac->renderQuality, "best"); + else + strcpy(ac->renderQuality, config_setting_get_string(setting)); + + setting = config_setting_get_member(root, "unfocused_comeback"); + if (setting == NULL) + ac->unfocusedComeback = 1; + else + ac->unfocusedComeback = config_setting_get_int(setting); + + setting = config_setting_get_member(root, "wnd_target_point"); + if (setting == NULL) + ac->wndTargetPoint = 0; + else + ac->wndTargetPoint = config_setting_get_int(setting); config_destroy(&cfg); - return 1; } -int loadWallpaperConfig(const char *dirPath, WallpaperConfig *wc) +int loadWallpaperConfig(const char* dirPath, WallpaperConfig* wc) { wc->loaded = 0; @@ -190,7 +212,7 @@ int loadWallpaperConfig(const char *dirPath, WallpaperConfig *wc) for (int i = 0; i < wc->layersCount; i++) { - LayerConfig *lc = wc->layerConfigs + i; + LayerConfig* lc = wc->layerConfigs + i; lc->sensitivityX = movX * i; lc->sensitivityY = movY * i; diff --git a/src/common/debug.c b/src/common/debug.c new file mode 100644 index 0000000..2f8248f --- /dev/null +++ b/src/common/debug.c @@ -0,0 +1,83 @@ +#include +#include +#include +#include + +#include "../common.h" + +void clearlog() +{ + char path[PATH_MAX]; + getLogPath(path); + + FILE *file = fopen(path, "w"); + fclose(file); +} + +void printlog(int type, const char *str, ...) +{ + char path[PATH_MAX]; + getLogPath(path); + + FILE *file = fopen(path, "a"); + + time_t t; + time(&t); + struct tm *time = localtime(&t); + + char *typePrefix = ""; + + switch (type) + { + case LOG_ERROR: + typePrefix = "ERROR"; + break; + case LOG_INFO: + typePrefix = "INFO"; + break; + case LOG_WARNING: + typePrefix = "WARNING"; + break; + } + + fprintf( + file, + "%d-%02d-%02d %02d:%02d:%02d %s: ", + time->tm_year + 1900, + time->tm_mon + 1, + time->tm_mday, + time->tm_hour, + time->tm_min, + time->tm_sec, + typePrefix + ); + + va_list args; + va_start(args, str); + vfprintf(file, str, args); + va_end(args); + + fprintf(file, "\n"); + + fclose(file); +} + +char *readLogFile() +{ + char path[PATH_MAX]; + getLogPath(path); + + FILE *file = fopen(path, "r"); + + fseek(file, 0, SEEK_END); + int len = ftell(file); + fseek(file, 0, SEEK_SET); + + char *buff = malloc((len + 1) * sizeof(char)); + fread(buff, sizeof(char), len, file); + buff[len] = '\0'; + + fclose(file); + + return buff; +} diff --git a/src/common/monitorScanner.c b/src/common/monitorScanner.c index dac0208..d6606e7 100644 --- a/src/common/monitorScanner.c +++ b/src/common/monitorScanner.c @@ -3,36 +3,116 @@ #include "../common.h" -#ifdef __WIN32 -#include -#else +#ifdef __LINUX #include #include +#include #endif #ifdef __WIN32 + int monitorEnumIndex = 0; -static BOOL monitorenumproc(HMONITOR monitor, HDC hdc, LPRECT rect, LPARAM param) +int primaryX = 0; +int primaryY = 0; + +static float getScalingFactor(HMONITOR monitor) +{ + DEVICE_SCALE_FACTOR rawScaleFactor; + HRESULT hr = GetScaleFactorForMonitor(monitor, &rawScaleFactor); + + return rawScaleFactor / 100; +} + +static void getMonitorName(int index, char *name, char *displayName) +{ + DISPLAY_DEVICE dd; + dd.cb = sizeof(DISPLAY_DEVICE); + EnumDisplayDevices(NULL, index, &dd, EDD_GET_DEVICE_INTERFACE_NAME); + DISPLAY_DEVICE dd2; + dd2.cb = sizeof(DISPLAY_DEVICE); + EnumDisplayDevices(dd.DeviceName, 0, &dd2, EDD_GET_DEVICE_INTERFACE_NAME); + + char *ptr = dd2.DeviceID; + while (*ptr != '#') ptr++; + ptr++; + + char *ptrEnd = ptr; + int hashes = 0; + while (hashes < 2) + { + ptrEnd++; + if (*ptrEnd == '#') hashes++; + } + *ptrEnd = '\0'; + + strncpy(displayName, dd2.DeviceString, MONITOR_NAME_MAX); + strncpy(name, ptr, MONITOR_NAME_MAX); +} + +static void getMonitorBounds( + HMONITOR monitor, Bounds *original, Bounds *client, Bounds *virtual +) +{ + MONITORINFOEX info; + info.cbSize = sizeof(MONITORINFOEX); + GetMonitorInfo(monitor, (LPMONITORINFO)&info); + + if (original) + { + original->x = info.rcMonitor.left; + original->y = info.rcMonitor.top; + original->w = info.rcMonitor.right - info.rcMonitor.left; + original->h = info.rcMonitor.bottom - info.rcMonitor.top; + } + + DEVMODE devmode; + devmode.dmSize = sizeof(DEVMODE); + EnumDisplaySettings(info.szDevice, ENUM_CURRENT_SETTINGS, &devmode); + + if (client) + { + client->x = devmode.dmPosition.x; + client->y = devmode.dmPosition.y; + client->w = devmode.dmPelsWidth; + client->h = devmode.dmPelsHeight; + } + + float scaleFactor = getScalingFactor(monitor); + + if (virtual) + { + virtual->x = devmode.dmPosition.x * scaleFactor - primaryX; + virtual->y = devmode.dmPosition.y * scaleFactor - primaryY; + virtual->w = devmode.dmPelsWidth * scaleFactor; + virtual->h = devmode.dmPelsHeight * scaleFactor; + } +} + +static BOOL monitorenumproc_FindPrimaryCoords( + HMONITOR monitor, HDC hdc, LPRECT rect, LPARAM param +) { - MONITORINFO info; - info.cbSize = sizeof(MONITORINFO); + Bounds bounds; + getMonitorBounds(monitor, NULL, &bounds, NULL); - GetMonitorInfo(monitor, &info); + if (bounds.x < primaryX) primaryX = bounds.x; + if (bounds.y < primaryY) primaryY = bounds.y; + return TRUE; +} + +static BOOL monitorenumproc_GetInfo( + HMONITOR monitor, HDC hdc, LPRECT rect, LPARAM param +) +{ MonitorInfo *mi = (MonitorInfo *)param + monitorEnumIndex; - snprintf( - mi->name, - MONITOR_NAME_MAX, - "Monitor %d%s", - monitorEnumIndex + 1, - info.dwFlags == MONITORINFOF_PRIMARY ? " (main)" : "" + getMonitorBounds( + monitor, &mi->pixelBounds, &mi->clientBounds, &mi->virtualBounds ); - mi->bounds.x = info.rcWork.left; - mi->bounds.y = info.rcWork.top; - mi->bounds.w = info.rcWork.right - info.rcWork.left; - mi->bounds.h = info.rcWork.bottom - info.rcWork.top; + getMonitorName(monitorEnumIndex, mi->name, mi->displayName); + mi->config.loaded = 0; monitorEnumIndex++; @@ -45,11 +125,15 @@ MonitorInfo *scanMonitors(int *count) MonitorInfo *m = NULL; #ifdef __WIN32 + EnumDisplayMonitors( + NULL, NULL, &monitorenumproc_FindPrimaryCoords, (LPARAM)NULL + ); + monitorEnumIndex = 0; *count = GetSystemMetrics(SM_CMONITORS); m = malloc(sizeof(MonitorInfo) * (*count)); - EnumDisplayMonitors(NULL, NULL, &monitorenumproc, (LPARAM)m); + EnumDisplayMonitors(NULL, NULL, &monitorenumproc_GetInfo, (LPARAM)m); #else int monitorCount; @@ -63,11 +147,19 @@ MonitorInfo *scanMonitors(int *count) int i = 0; while (i < monitorCount) { - snprintf(m[i].name, MONITOR_NAME_MAX, "%s", XGetAtomName(display, info->name)); - m[i].bounds.x = info->x; - m[i].bounds.y = info->y; - m[i].bounds.w = info->width; - m[i].bounds.h = info->height; + snprintf( + m[i].name, MONITOR_NAME_MAX, "%s", XGetAtomName(display, info->name) + ); + strcpy(m[i].displayName, m[i].name); + + m[i].virtualBounds.x = info->x; + m[i].virtualBounds.y = info->y; + m[i].virtualBounds.w = info->width; + m[i].virtualBounds.h = info->height; + + memcpy(&m[i].clientBounds, &m[i].virtualBounds, sizeof(Bounds)); + memcpy(&m[i].pixelBounds, &m[i].virtualBounds, sizeof(Bounds)); + m[i].config.loaded = 0; info++; diff --git a/src/core/CMakeLists.txt b/src/core/CMakeLists.txt index b0eaa33..d13e80e 100644 --- a/src/core/CMakeLists.txt +++ b/src/core/CMakeLists.txt @@ -3,7 +3,8 @@ set(_SOURCE_FILES ../common/config.c ../common/wallpaperScanner.c ../common/monitorScanner.c - main.c + ../common/debug.c + main.c windowHandlers.c wlp.c trayIcon.c @@ -46,6 +47,11 @@ pkg_check_modules (libconfig REQUIRED libconfig) list(APPEND _INCLUDE_DIRS ${libconfig_INCLUDE_DIRS}) list(APPEND _LIBS ${libconfig_LINK_LIBRARIES}) +if (_UNAME STREQUAL "WIN32") + # Shcore dependency + list(APPEND _LIBS "-lShcore") +endif() + # Main executable if(_UNAME STREQUAL "WIN32") add_executable(lwp WIN32 ${_SOURCE_FILES}) diff --git a/src/core/main.c b/src/core/main.c index afd7ed2..9d2686f 100644 --- a/src/core/main.c +++ b/src/core/main.c @@ -1,52 +1,50 @@ #include "main.h" -#include "../platform_guard.h" +#ifdef __WIN32 +HANDLE hJob = NULL; +#endif GtkApplication *app = NULL; GtkBuilder *builder = NULL; -GtkWidget *mainWnd = NULL; -GtkWidget *exitDialog = NULL; -GtkWidget *wallpaperMgrWnd = NULL; -GtkWidget *monitorWnd = NULL; -GtkWidget *monitorListBox = NULL; -GtkWidget *wallpaperListBox = NULL; -GtkWidget *wallpaperComboBox = NULL; -GtkWidget *xPosSpinBtn = NULL; -GtkWidget *yPosSpinBtn = NULL; -GtkWidget *widthSpinBtn = NULL; -GtkWidget *heightSpinBtn = NULL; -GtkWidget *monitorNameLabel = NULL; -GtkWidget *versionLabel = NULL; -GtkWidget *appSettingsWnd = NULL; -GtkWidget *targetFpsComboBox = NULL; -GtkWidget *renderQualityComboBox = NULL; -GtkWidget *drawOnRootWndComboBox = NULL; +Control controls[] = { + {.name = "MainWindow"}, + {.name = "Mon_List"}, + {.name = "Mon_Switch"}, + {.name = "Mon_Wallpaper"}, + {.name = "Mon_OffsetX"}, + {.name = "Mon_OffsetY"}, + {.name = "Mon_Width"}, + {.name = "Mon_Height"}, + {.name = "App_TargetFps"}, + {.name = "App_TexFiltering"}, + {.name = "App_UnfocusedBehaviour"}, + {.name = "App_TargetPoint"}, + {.name = "VersionLabel"}, + {.name = "MainStack"}, + {.name = "Sidebar"}, + {.name = "Mon_AspectRatio"}, + {.name = "LogWindow"}, + {.name = "Log_Text"}, +}; static void reloadMonitorListBox() { - GList *rows = gtk_container_get_children(GTK_CONTAINER(monitorListBox)); + GList *rows = + gtk_container_get_children(GTK_CONTAINER(controls[CONTROL_MON_LIST].widget + )); GList *ptr = rows; while (ptr) { - gtk_container_remove(GTK_CONTAINER(monitorListBox), ptr->data); + gtk_container_remove( + GTK_CONTAINER(controls[CONTROL_MON_LIST].widget), ptr->data + ); ptr = ptr->next; } g_list_free(rows); - char iconPath[PATH_MAX]; - getAppDir(iconPath, APP_DIR_SHARE); -#ifdef __WIN32 - const char *format = "%s\\%s\\%s\\%s"; -#else - const char *format = "%s/%s/%s/%s"; -#endif - sprintf( - iconPath, format, iconPath, "window_templates", "assets", "screen-monitor-svgrepo-com.svg" - ); - int monitorsCount; MonitorInfo *monitors; @@ -55,16 +53,22 @@ static void reloadMonitorListBox() for (int i = 0; i < monitorsCount; i++) { char resStr[12]; - sprintf(resStr, "%dx%d", monitors[i].bounds.w, monitors[i].bounds.h); + sprintf( + resStr, "%dx%d", monitors[i].clientBounds.w, monitors[i].clientBounds.h + ); - GtkWidget *nameLabel = gtk_label_new(monitors[i].name); + GtkWidget *nameLabel = gtk_label_new(monitors[i].displayName); GtkWidget *resLabel = gtk_label_new(resStr); - GtkWidget *icon = gtk_image_new_from_file(iconPath); + GtkWidget *icon = + gtk_image_new_from_icon_name("video-display", GTK_ICON_SIZE_DIALOG); + gtk_widget_set_margin_start(icon, 10); GtkWidget *labelBox = gtk_box_new(GTK_ORIENTATION_VERTICAL, 0); gtk_container_add(GTK_CONTAINER(labelBox), nameLabel); gtk_container_add(GTK_CONTAINER(labelBox), resLabel); - gtk_box_set_child_packing(GTK_BOX(labelBox), nameLabel, 1, 1, 0, GTK_PACK_START); + gtk_box_set_child_packing( + GTK_BOX(labelBox), nameLabel, 1, 1, 0, GTK_PACK_START + ); GtkWidget *box = gtk_box_new(GTK_ORIENTATION_HORIZONTAL, 0); gtk_container_add(GTK_CONTAINER(box), icon); @@ -74,12 +78,29 @@ static void reloadMonitorListBox() GtkWidget *row = gtk_list_box_row_new(); gtk_container_add(GTK_CONTAINER(row), box); - gtk_list_box_insert(GTK_LIST_BOX(monitorListBox), row, 0); + gtk_list_box_insert( + GTK_LIST_BOX(controls[CONTROL_MON_LIST].widget), row, 0 + ); - char *nameBuff = malloc(strlen(monitors[i].name)+1); + char *nameBuff = malloc(strlen(monitors[i].name) + 1); strcpy(nameBuff, monitors[i].name); + char *displayNameBuff = malloc(strlen(monitors[i].displayName) + 1); + strcpy(displayNameBuff, monitors[i].displayName); + + g_object_set_data( + G_OBJECT(row), "monitor_display_name", (gpointer)displayNameBuff + ); + + int *width = (int *)malloc(sizeof(int)); + int *height = (int *)malloc(sizeof(int)); + + *width = monitors[i].pixelBounds.w; + *height = monitors[i].pixelBounds.h; + g_object_set_data(G_OBJECT(row), "monitor_name", (gpointer)nameBuff); + g_object_set_data(G_OBJECT(row), "monitor_width", (gpointer)width); + g_object_set_data(G_OBJECT(row), "monitor_height", (gpointer)height); gtk_widget_show_all(row); } @@ -103,44 +124,27 @@ static void activate(GtkApplication *app, gpointer userdata) builder = gtk_builder_new_from_file(gladefilePath); gtk_builder_connect_signals(builder, NULL); - mainWnd = (GtkWidget *)gtk_builder_get_object(builder, "MainWindow"); - exitDialog = (GtkWidget *)gtk_builder_get_object(builder, "ExitDialog"); - wallpaperMgrWnd = (GtkWidget *)gtk_builder_get_object(builder, "WallpaperManagerWindow"); - monitorWnd = (GtkWidget *)gtk_builder_get_object(builder, "MonitorWindow"); - appSettingsWnd = (GtkWidget *)gtk_builder_get_object(builder, "SettingsWindow"); - monitorListBox = (GtkWidget *)gtk_builder_get_object(builder, "MainWindow_MonitorListBox"); - versionLabel = (GtkWidget *)gtk_builder_get_object(builder, "MainWindow_VersionLabel"); - wallpaperListBox = - (GtkWidget *)gtk_builder_get_object(builder, "WallpaperManagerWindow_WallpaperListBox"); - wallpaperComboBox = - (GtkWidget *)gtk_builder_get_object(builder, "MonitorWindow_WallpaperComboBox"); - xPosSpinBtn = (GtkWidget *)gtk_builder_get_object(builder, "MonitorWindow_XPosSpinBtn"); - yPosSpinBtn = (GtkWidget *)gtk_builder_get_object(builder, "MonitorWindow_YPosSpinBtn"); - widthSpinBtn = (GtkWidget *)gtk_builder_get_object(builder, "MonitorWindow_WidthSpinBtn"); - heightSpinBtn = (GtkWidget *)gtk_builder_get_object(builder, "MonitorWindow_HeightSpinBtn"); - monitorNameLabel = - (GtkWidget *)gtk_builder_get_object(builder, "MonitorWindow_MonitorNameLabel"); - targetFpsComboBox = - (GtkWidget *)gtk_builder_get_object(builder, "SettingsWindow_TargetFpsComboBox"); - renderQualityComboBox = - (GtkWidget *)gtk_builder_get_object(builder, "SettingsWindow_TexFilteringComboBox"); - drawOnRootWndComboBox = - (GtkWidget *)gtk_builder_get_object(builder, "SettingsWindow_DrawOnRootWndComboBox"); - - gtk_window_set_application(GTK_WINDOW(mainWnd), GTK_APPLICATION(app)); - gtk_window_set_application(GTK_WINDOW(exitDialog), GTK_APPLICATION(app)); - gtk_window_set_application(GTK_WINDOW(wallpaperMgrWnd), GTK_APPLICATION(app)); - gtk_window_set_application(GTK_WINDOW(monitorWnd), GTK_APPLICATION(app)); - gtk_window_set_application(GTK_WINDOW(appSettingsWnd), GTK_APPLICATION(app)); - - gtk_label_set_text(GTK_LABEL(versionLabel), PROGRAM_VERSION); + for (int i = 0; i < CONTROLS_MAX; i++) + controls[i].widget = + (GtkWidget *)gtk_builder_get_object(builder, controls[i].name); + + gtk_window_set_title( + GTK_WINDOW(WID(CONTROL_MAIN_WND)), "Layered WallPaper" + ); + + gtk_window_set_application( + GTK_WINDOW(WID(CONTROL_MAIN_WND)), GTK_APPLICATION(app) + ); + + gtk_label_set_text(GTK_LABEL(WID(CONTROL_VER_LABEL)), PROGRAM_VERSION); runWlp(); } reloadMonitorListBox(); - if (alreadyRunning) gtk_widget_set_visible(mainWnd, 1); + if (alreadyRunning) + gtk_widget_set_visible(controls[CONTROL_MAIN_WND].widget, 1); alreadyRunning = 1; } @@ -152,10 +156,22 @@ int main(int argc, char *argv[]) createUserDirs(); #ifdef __WIN32 + hJob = CreateJobObject(NULL, NULL); + AssignProcessToJobObject(hJob, GetCurrentProcess()); + SetEnvironmentVariable("GTK_THEME", "Adwaita:dark"); initTrayIcon(); #endif - app = gtk_application_new("com.github.jszczerbinsky.lwp", G_APPLICATION_DEFAULT_FLAGS); +#if GLIB_CHECK_VERSION(2, 74, 0) + app = gtk_application_new( + "com.github.jszczerbinsky.lwp", G_APPLICATION_DEFAULT_FLAGS + ); +#else + app = gtk_application_new( + "com.github.jszczerbinsky.lwp", G_APPLICATION_FLAGS_NONE + ); +#endif + g_signal_connect(app, "activate", G_CALLBACK(activate), NULL); status = g_application_run(G_APPLICATION(app), argc, argv); g_object_unref(app); diff --git a/src/core/main.h b/src/core/main.h index b775e33..bc9e021 100644 --- a/src/core/main.h +++ b/src/core/main.h @@ -1,28 +1,47 @@ #ifndef MAIN_H #define MAIN_H +#include "../platform_guard.h" + #include #include "../common.h" -extern GtkApplication *app; - -extern GtkWidget *mainWnd; -extern GtkWidget *exitDialog; -extern GtkWidget *wallpaperMgrWnd; -extern GtkWidget *monitorWnd; -extern GtkWidget *monitorListBox; -extern GtkWidget *wallpaperListBox; -extern GtkWidget *wallpaperComboBox; -extern GtkWidget *xPosSpinBtn; -extern GtkWidget *yPosSpinBtn; -extern GtkWidget *widthSpinBtn; -extern GtkWidget *heightSpinBtn; -extern GtkWidget *monitorNameLabel; -extern GtkWidget *appSettingsWnd; -extern GtkWidget *targetFpsComboBox; -extern GtkWidget *renderQualityComboBox; -extern GtkWidget *drawOnRootWndComboBox; +#ifdef __WIN32 +extern HANDLE hJob; +#endif + +extern GtkApplication* app; + +#define CONTROL_MAIN_WND 0 +#define CONTROL_MON_LIST 1 +#define CONTROL_MON_SWITCH 2 +#define CONTROL_MON_WLP 3 +#define CONTROL_MON_OFFSET_X 4 +#define CONTROL_MON_OFFSET_Y 5 +#define CONTROL_MON_WIDTH 6 +#define CONTROL_MON_HEIGHT 7 +#define CONTROL_APP_TARGET_FPS 8 +#define CONTROL_APP_TEX_FILTERING 9 +#define CONTROL_APP_UNFOCUSED_BEHAVIOUR 10 +#define CONTROL_APP_TARGET_POINT 11 +#define CONTROL_VER_LABEL 12 +#define CONTROL_MAIN_STACK 13 +#define CONTROL_SIDEBAR 14 +#define CONTROL_MON_ASPECT_RATIO 15 +#define CONTROL_LOG_WINDOW 16 +#define CONTROL_LOG_TEXT 17 + +#define CONTROLS_MAX 18 + +typedef struct { + const char* name; + GtkWidget* widget; +} Control; + +extern Control controls[]; + +#define WID(x) (controls[(x)].widget) void runWlp(); void killWlp(); diff --git a/src/core/resource.template.rc b/src/core/resource.template.rc index 16de8c9..ee27d3c 100644 --- a/src/core/resource.template.rc +++ b/src/core/resource.template.rc @@ -3,7 +3,7 @@ #define PROGRAM_VER "@PROGRAM_VERSION@" -id ICON "..\..\icon.ico" +id ICON "../../icon.ico" VS_VERSION_INFO VERSIONINFO FILEOS VOS_NT @@ -19,7 +19,7 @@ BEGIN VALUE "FileVersion", PROGRAM_VER VALUE "InternalName", "Layered WallPaper" VALUE "LegalCopyright", "(c) 2022 Jakub SzczerbiƄski" - VALUE "OriginalFilename", "lwpwlp.exe" + VALUE "OriginalFilename", "lwp.exe" VALUE "ProductName", "Layered WallPaper" VALUE "ProductVersion", PROGRAM_VER END diff --git a/src/core/trayIcon.c b/src/core/trayIcon.c index e4d1473..990cc0e 100644 --- a/src/core/trayIcon.c +++ b/src/core/trayIcon.c @@ -1,22 +1,18 @@ #ifdef __WIN32 -#include -#include -#include - #include "main.h" +#include + #define WM_TRAY_ICON (WM_USER + 1) static NOTIFYICONDATA nid; void removeTrayIcon() { Shell_NotifyIcon(NIM_DELETE, &nid); } -int updateTrayIcon() -{ +int updateTrayIcon() { MSG msg; - while (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE)) - { + while (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE)) { TranslateMessage(&msg); DispatchMessage(&msg); } @@ -24,21 +20,18 @@ int updateTrayIcon() return 1; } -static LRESULT CALLBACK wndProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam) -{ - switch (uMsg) - { - case WM_TRAY_ICON: - if (lParam == WM_RBUTTONDOWN || lParam == WM_LBUTTONDOWN) - { - gtk_widget_set_visible(mainWnd, 1); - } - break; +static LRESULT CALLBACK wndProc(HWND hwnd, UINT uMsg, WPARAM wParam, + LPARAM lParam) { + switch (uMsg) { + case WM_TRAY_ICON: + if (lParam == WM_RBUTTONDOWN || lParam == WM_LBUTTONDOWN) { + gtk_widget_set_visible(controls[CONTROL_MAIN_WND].widget, 1); + } + break; } } -void initTrayIcon() -{ +void initTrayIcon() { // Create an invisible window to process tray icon events HINSTANCE hInstance = GetModuleHandle(NULL); @@ -49,20 +42,9 @@ void initTrayIcon() wc.hInstance = hInstance; wc.lpszClassName = CLASS_NAME; RegisterClass(&wc); - HWND hWnd = CreateWindowEx( - 0, - CLASS_NAME, - TEXT(""), - WS_OVERLAPPEDWINDOW, - CW_USEDEFAULT, - CW_USEDEFAULT, - CW_USEDEFAULT, - CW_USEDEFAULT, - NULL, - NULL, - hInstance, - NULL - ); + HWND hWnd = CreateWindowEx(0, CLASS_NAME, TEXT(""), WS_OVERLAPPEDWINDOW, + CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, + CW_USEDEFAULT, NULL, NULL, hInstance, NULL); // Create tray icon diff --git a/src/core/windowHandlers.c b/src/core/windowHandlers.c index bc75cfa..1e43360 100644 --- a/src/core/windowHandlers.c +++ b/src/core/windowHandlers.c @@ -1,43 +1,65 @@ #include "main.h" -// Exit Dialog handlers +#define VIEW_MON 0 +#define VIEW_SETTINGS 1 + +static int currentView = VIEW_MON; -G_MODULE_EXPORT void ExitDialogClose() { gtk_widget_set_visible(exitDialog, 0); } +// Exit Dialog handlers +/* +G_MODULE_EXPORT void ExitDialogClose() +{ + gtk_widget_set_visible(exitDialog, 0); +} -G_MODULE_EXPORT void ExitDialog_No() { gtk_widget_set_visible(exitDialog, 0); } +G_MODULE_EXPORT void ExitDialog_No() { gtk_widget_set_visible(exitDialog, +0); } G_MODULE_EXPORT void ExitDialog_Yes() { killWlp(); g_application_quit(G_APPLICATION(app)); -} +}*/ // Main Window handlers - +/* G_MODULE_EXPORT void MainWindow_ManageWallpapersBtnClick() { - GtkDialogFlags flags = GTK_DIALOG_DESTROY_WITH_PARENT; - GtkWidget *dialog = gtk_message_dialog_new (GTK_WINDOW(mainWnd), + GtkDialogFlags flags = GTK_DIALOG_DESTROY_WITH_PARENT; + GtkWidget *dialog = gtk_message_dialog_new( + GTK_WINDOW(mainWnd), flags, GTK_MESSAGE_ERROR, GTK_BUTTONS_CLOSE, - "This feature will be available in the future"); - gtk_dialog_run (GTK_DIALOG (dialog)); - gtk_widget_destroy (dialog); - //gtk_widget_set_visible(wallpaperMgrWnd, 1); + "This feature will be available in the future" + ); + gtk_dialog_run(GTK_DIALOG(dialog)); + gtk_widget_destroy(dialog); + // gtk_widget_set_visible(wallpaperMgrWnd, 1); } -G_MODULE_EXPORT void MainWindow_MonitorEditBtnClick() { gtk_widget_set_visible(monitorWnd, 1); } +G_MODULE_EXPORT void MainWindow_MonitorEditBtnClick() +{ + gtk_widget_set_visible(monitorWnd, 1); +} -G_MODULE_EXPORT void MainWindow_ExitBtnClick() { gtk_widget_set_visible(exitDialog, 1); } +G_MODULE_EXPORT void MainWindow_ExitBtnClick() +{ + gtk_widget_set_visible(exitDialog, 1); +} -G_MODULE_EXPORT void MainWindow_AppSettingsBtnClick() { gtk_widget_set_visible(appSettingsWnd, 1); } +G_MODULE_EXPORT void MainWindow_AppSettingsBtnClick() +{ + gtk_widget_set_visible(appSettingsWnd, 1); +} -G_MODULE_EXPORT void MainWindowClose() { gtk_widget_set_visible(mainWnd, 0); } // Wallpapaer Manager Window handlers -G_MODULE_EXPORT void WallpaperManagerWindowClose() { gtk_widget_set_visible(wallpaperMgrWnd, 0); } +G_MODULE_EXPORT void WallpaperManagerWindowClose() +{ + gtk_widget_set_visible(wallpaperMgrWnd, 0); +} G_MODULE_EXPORT void WallpaperManagerWindowShow() { @@ -59,7 +81,10 @@ G_MODULE_EXPORT void WallpaperManagerWindowShow() // Monitor Window handlers -G_MODULE_EXPORT void MonitorWindowClose() { gtk_widget_set_visible(monitorWnd, 0); } +G_MODULE_EXPORT void MonitorWindowClose() +{ + gtk_widget_set_visible(monitorWnd, 0); +} G_MODULE_EXPORT void MonitorWindowShow() { // Clear wallpaper list @@ -72,7 +97,10 @@ G_MODULE_EXPORT void MonitorWindowShow() for (int i = 0; i < wlpCount; i++) { gtk_combo_box_text_insert( - GTK_COMBO_BOX_TEXT(wallpaperComboBox), 0, wlpList[i].name, wlpList[i].name + GTK_COMBO_BOX_TEXT(wallpaperComboBox), + 0, + wlpList[i].name, + wlpList[i].name ); } gtk_combo_box_set_active(GTK_COMBO_BOX(wallpaperComboBox), 0); @@ -80,39 +108,68 @@ G_MODULE_EXPORT void MonitorWindowShow() free(wlpList); // Find selected monitor name - GtkListBoxRow *listBoxRow = gtk_list_box_get_selected_row(GTK_LIST_BOX(monitorListBox)); - const char *monitorName = g_object_get_data(G_OBJECT(listBoxRow), "monitor_name"); - gtk_label_set_text(GTK_LABEL(monitorNameLabel), monitorName); + GtkListBoxRow *listBoxRow = + gtk_list_box_get_selected_row(GTK_LIST_BOX(monitorListBox)); + const char *monitorDisplayName = + g_object_get_data(G_OBJECT(listBoxRow), "monitor_display_name"); + const char *monitorName = + g_object_get_data(G_OBJECT(listBoxRow), "monitor_name"); + gtk_label_set_text(GTK_LABEL(monitorNameLabel), monitorDisplayName); + + char *nameBuff = strdup(monitorName); + g_object_set_data(G_OBJECT(monitorWnd), "monitor_name", +(gpointer)nameBuff); // Read configuration from config file MonitorConfig mc; if (loadMonitorConfig(monitorName, &mc)) { - gtk_spin_button_set_value(GTK_SPIN_BUTTON(xPosSpinBtn), (gdouble)mc.wlpBounds.x); - gtk_spin_button_set_value(GTK_SPIN_BUTTON(yPosSpinBtn), (gdouble)mc.wlpBounds.y); - gtk_spin_button_set_value(GTK_SPIN_BUTTON(widthSpinBtn), (gdouble)mc.wlpBounds.w); - gtk_spin_button_set_value(GTK_SPIN_BUTTON(heightSpinBtn), (gdouble)mc.wlpBounds.h); + gtk_spin_button_set_value( + GTK_SPIN_BUTTON(xPosSpinBtn), (gdouble)mc.wlpBounds.x + ); + gtk_spin_button_set_value( + GTK_SPIN_BUTTON(yPosSpinBtn), (gdouble)mc.wlpBounds.y + ); + gtk_spin_button_set_value( + GTK_SPIN_BUTTON(widthSpinBtn), (gdouble)mc.wlpBounds.w + ); + gtk_spin_button_set_value( + GTK_SPIN_BUTTON(heightSpinBtn), (gdouble)mc.wlpBounds.h + ); - gtk_combo_box_set_active_id(GTK_COMBO_BOX(wallpaperComboBox), mc.wlpName); + gtk_combo_box_set_active_id(GTK_COMBO_BOX(wallpaperComboBox), +mc.wlpName); } } G_MODULE_EXPORT void MonitorWindow_ApplyBtnClick() { MonitorConfig mc; - strcpy(mc.wlpName, gtk_combo_box_get_active_id(GTK_COMBO_BOX(wallpaperComboBox))); - mc.wlpBounds.x = gtk_spin_button_get_value_as_int(GTK_SPIN_BUTTON(xPosSpinBtn)); - mc.wlpBounds.y = gtk_spin_button_get_value_as_int(GTK_SPIN_BUTTON(yPosSpinBtn)); - mc.wlpBounds.w = gtk_spin_button_get_value_as_int(GTK_SPIN_BUTTON(widthSpinBtn)); - mc.wlpBounds.h = gtk_spin_button_get_value_as_int(GTK_SPIN_BUTTON(heightSpinBtn)); - - saveMonitorConfig(gtk_label_get_text(GTK_LABEL(monitorNameLabel)), &mc); + strcpy( + mc.wlpName, +gtk_combo_box_get_active_id(GTK_COMBO_BOX(wallpaperComboBox)) + ); + mc.wlpBounds.x = + gtk_spin_button_get_value_as_int(GTK_SPIN_BUTTON(xPosSpinBtn)); + mc.wlpBounds.y = + gtk_spin_button_get_value_as_int(GTK_SPIN_BUTTON(yPosSpinBtn)); + mc.wlpBounds.w = + gtk_spin_button_get_value_as_int(GTK_SPIN_BUTTON(widthSpinBtn)); + mc.wlpBounds.h = + gtk_spin_button_get_value_as_int(GTK_SPIN_BUTTON(heightSpinBtn)); + + saveMonitorConfig( + g_object_get_data(G_OBJECT(monitorWnd), "monitor_name"), &mc + ); killWlp(); runWlp(); } -G_MODULE_EXPORT void MonitorWindow_ExitBtnClick() { gtk_widget_set_visible(monitorWnd, 0); } +G_MODULE_EXPORT void MonitorWindow_ExitBtnClick() +{ + gtk_widget_set_visible(monitorWnd, 0); +} // App Settings Window handlers @@ -124,25 +181,204 @@ G_MODULE_EXPORT void SettingsWindowShow() char targetFpsStr[4]; sprintf(targetFpsStr, "%d", ac.targetFps); -#ifdef __LINUX - char drawOnRootWindowStr[2]; - sprintf(drawOnRootWindowStr, "%d", ac.drawOnRootWindow); -#else - char *drawOnRootWindowStr = "0"; -#endif - gtk_combo_box_set_active_id(GTK_COMBO_BOX(renderQualityComboBox), ac.renderQuality); + char unfocusedComebackStr[2]; + sprintf(unfocusedComebackStr, "%d", ac.unfocusedComeback); + + char targetPointStr[2]; + sprintf(targetPointStr, "%d", ac.wndTargetPoint); + + gtk_combo_box_set_active_id( + GTK_COMBO_BOX(renderQualityComboBox), ac.renderQuality + ); +<<<<<<< HEAD + gtk_combo_box_set_active_id(GTK_COMBO_BOX(targetFpsComboBox), +targetFpsStr); +======= gtk_combo_box_set_active_id(GTK_COMBO_BOX(targetFpsComboBox), targetFpsStr); - gtk_combo_box_set_active_id(GTK_COMBO_BOX(drawOnRootWndComboBox), drawOnRootWindowStr); + gtk_combo_box_set_active_id( + GTK_COMBO_BOX(unfocusedComebackComboBox), unfocusedComebackStr + ); + gtk_combo_box_set_active_id( + GTK_COMBO_BOX(targetPointComboBox), targetPointStr + ); +>>>>>>> enhanced-target-point } -G_MODULE_EXPORT void SettingsWindowClose() { gtk_widget_set_visible(appSettingsWnd, 0); } +G_MODULE_EXPORT void SettingsWindowClose() +{ + gtk_widget_set_visible(appSettingsWnd, 0); +} G_MODULE_EXPORT void SettingsWindow_ApplyBtnClick() { AppConfig ac; - strcpy(ac.renderQuality, gtk_combo_box_get_active_id(GTK_COMBO_BOX(renderQualityComboBox))); - ac.targetFps = atoi(gtk_combo_box_get_active_id(GTK_COMBO_BOX(targetFpsComboBox))); - ac.drawOnRootWindow = atoi(gtk_combo_box_get_active_id(GTK_COMBO_BOX(drawOnRootWndComboBox))); + strcpy( + ac.renderQuality, + gtk_combo_box_get_active_id(GTK_COMBO_BOX(renderQualityComboBox)) + ); + ac.targetFps = + atoi(gtk_combo_box_get_active_id(GTK_COMBO_BOX(targetFpsComboBox))); + + ac.unfocusedComeback = + atoi(gtk_combo_box_get_active_id(GTK_COMBO_BOX(unfocusedComebackComboBox)) + ); + + ac.wndTargetPoint = + atoi(gtk_combo_box_get_active_id(GTK_COMBO_BOX(targetPointComboBox))); + + saveAppConfig(&ac); + + killWlp(); + runWlp(); +} + +G_MODULE_EXPORT void SettingsWindow_ExitBtnClick() +{ + gtk_widget_set_visible(appSettingsWnd, 0); +} +*/ + +static void reloadWlpList() +{ + gtk_combo_box_text_remove_all(GTK_COMBO_BOX_TEXT(WID(CONTROL_MON_WLP))); + + int wlpCount; + WallpaperInfo *wlpList = scanWallpapers(&wlpCount); + + for (int i = 0; i < wlpCount; i++) + { + gtk_combo_box_text_insert( + GTK_COMBO_BOX_TEXT(WID(CONTROL_MON_WLP)), + 0, + wlpList[i].name, + wlpList[i].name + ); + } + + gtk_combo_box_set_active(GTK_COMBO_BOX(WID(CONTROL_MON_WLP)), 0); +} + +static const char *getSelectedMonName() +{ + GtkListBoxRow *row = + gtk_list_box_get_selected_row(GTK_LIST_BOX(WID(CONTROL_MON_LIST))); + + return g_object_get_data(G_OBJECT(row), "monitor_name"); +} + +static int getSelectedMonWidth() +{ + GtkListBoxRow *row = + gtk_list_box_get_selected_row(GTK_LIST_BOX(WID(CONTROL_MON_LIST))); + + return *(int *)g_object_get_data(G_OBJECT(row), "monitor_width"); +} +static int getSelectedMonHeight() +{ + GtkListBoxRow *row = + gtk_list_box_get_selected_row(GTK_LIST_BOX(WID(CONTROL_MON_LIST))); + + return *(int *)g_object_get_data(G_OBJECT(row), "monitor_height"); +} + +static void reloadAppSettings() +{ + AppConfig ac; + loadAppConfig(&ac); + + char targetFpsStr[4]; + sprintf(targetFpsStr, "%d", ac.targetFps); + + char unfocusedBehaviourStr[10]; + sprintf(unfocusedBehaviourStr, "%d", ac.unfocusedComeback); + + char targetPointStr[15]; + sprintf(targetPointStr, "%d", ac.wndTargetPoint); + + gtk_combo_box_set_active_id( + GTK_COMBO_BOX(WID(CONTROL_APP_TEX_FILTERING)), ac.renderQuality + ); + gtk_combo_box_set_active_id( + GTK_COMBO_BOX(WID(CONTROL_APP_TARGET_FPS)), targetFpsStr + ); + gtk_combo_box_set_active_id( + GTK_COMBO_BOX(WID(CONTROL_APP_UNFOCUSED_BEHAVIOUR)), unfocusedBehaviourStr + ); + gtk_combo_box_set_active_id( + GTK_COMBO_BOX(WID(CONTROL_APP_TARGET_POINT)), targetPointStr + ); +} + +static void reloadMonSettings() +{ + const char *monitor_name = getSelectedMonName(); + + MonitorConfig mc; + if (loadMonitorConfig(monitor_name, &mc)) + { + gtk_spin_button_set_value( + GTK_SPIN_BUTTON(WID(CONTROL_MON_OFFSET_X)), (gdouble)mc.wlpBounds.x + ); + gtk_spin_button_set_value( + GTK_SPIN_BUTTON(WID(CONTROL_MON_OFFSET_Y)), (gdouble)mc.wlpBounds.y + ); + gtk_spin_button_set_value( + GTK_SPIN_BUTTON(WID(CONTROL_MON_WIDTH)), (gdouble)mc.wlpBounds.w + ); + gtk_spin_button_set_value( + GTK_SPIN_BUTTON(WID(CONTROL_MON_HEIGHT)), (gdouble)mc.wlpBounds.h + ); + + gtk_combo_box_set_active_id( + GTK_COMBO_BOX(WID(CONTROL_MON_WLP)), mc.wlpName + ); + + gtk_switch_set_active(GTK_SWITCH(WID(CONTROL_MON_SWITCH)), mc.active); + } +} + +static void saveMonitor() +{ + MonitorConfig mc; + strcpy( + mc.wlpName, + gtk_combo_box_get_active_id(GTK_COMBO_BOX(WID(CONTROL_MON_WLP))) + ); + mc.wlpBounds.x = + gtk_spin_button_get_value_as_int(GTK_SPIN_BUTTON(WID(CONTROL_MON_OFFSET_X) + )); + mc.wlpBounds.y = + gtk_spin_button_get_value_as_int(GTK_SPIN_BUTTON(WID(CONTROL_MON_OFFSET_Y) + )); + mc.wlpBounds.w = + gtk_spin_button_get_value_as_int(GTK_SPIN_BUTTON(WID(CONTROL_MON_WIDTH))); + mc.wlpBounds.h = + gtk_spin_button_get_value_as_int(GTK_SPIN_BUTTON(WID(CONTROL_MON_HEIGHT)) + ); + mc.active = gtk_switch_get_active(GTK_SWITCH(WID(CONTROL_MON_SWITCH))); + + saveMonitorConfig(getSelectedMonName(), &mc); + + killWlp(); + runWlp(); +} + +static void saveApp() +{ + AppConfig ac; + strcpy( + ac.renderQuality, + gtk_combo_box_get_active_id(GTK_COMBO_BOX(WID(CONTROL_APP_TEX_FILTERING))) + ); + ac.targetFps = atoi( + gtk_combo_box_get_active_id(GTK_COMBO_BOX(WID(CONTROL_APP_TARGET_FPS))) + ); + ac.unfocusedComeback = atoi(gtk_combo_box_get_active_id( + GTK_COMBO_BOX(WID(CONTROL_APP_UNFOCUSED_BEHAVIOUR)) + )); + ac.wndTargetPoint = atoi( + gtk_combo_box_get_active_id(GTK_COMBO_BOX(WID(CONTROL_APP_TARGET_POINT))) + ); saveAppConfig(&ac); @@ -150,4 +386,127 @@ G_MODULE_EXPORT void SettingsWindow_ApplyBtnClick() runWlp(); } -G_MODULE_EXPORT void SettingsWindow_ExitBtnClick() { gtk_widget_set_visible(appSettingsWnd, 0); } +G_MODULE_EXPORT void LogWindowClose() +{ + gtk_widget_set_visible(WID(CONTROL_LOG_WINDOW), 0); +} + +G_MODULE_EXPORT void LogClick() +{ + gtk_widget_set_visible(WID(CONTROL_LOG_WINDOW), 1); + + char *content = readLogFile(); + + GtkTextBuffer *buff = + gtk_text_view_get_buffer(GTK_TEXT_VIEW(WID(CONTROL_LOG_TEXT))); + + gtk_text_buffer_set_text(buff, content, -1); + + free(content); +} + +G_MODULE_EXPORT void TurnOffClick() +{ + killWlp(); + g_application_quit(G_APPLICATION(app)); +} + +int aspect_ratio_ignore = 0; + +G_MODULE_EXPORT void MonChangeWidth() +{ + if (!aspect_ratio_ignore && + gtk_switch_get_active(GTK_SWITCH(WID(CONTROL_MON_ASPECT_RATIO)))) + { + int originalW = getSelectedMonWidth(); + int originalH = getSelectedMonHeight(); + + int width = + gtk_spin_button_get_value_as_int(GTK_SPIN_BUTTON(WID(CONTROL_MON_WIDTH)) + ); + + float ratio = (float)width / originalW; + + aspect_ratio_ignore = 1; + gtk_spin_button_set_value( + GTK_SPIN_BUTTON(WID(CONTROL_MON_HEIGHT)), (gdouble)(originalH * ratio) + ); + aspect_ratio_ignore = 0; + } +} + +G_MODULE_EXPORT void MonChangeHeight() +{ + if (!aspect_ratio_ignore && + gtk_switch_get_active(GTK_SWITCH(WID(CONTROL_MON_ASPECT_RATIO)))) + { + int originalW = getSelectedMonWidth(); + int originalH = getSelectedMonHeight(); + + int height = + gtk_spin_button_get_value_as_int(GTK_SPIN_BUTTON(WID(CONTROL_MON_HEIGHT) + )); + + float ratio = (float)height / originalH; + + aspect_ratio_ignore = 1; + gtk_spin_button_set_value( + GTK_SPIN_BUTTON(WID(CONTROL_MON_WIDTH)), (gdouble)(originalW * ratio) + ); + aspect_ratio_ignore = 0; + } +} + +G_MODULE_EXPORT void SaveClick() +{ + if (currentView == VIEW_MON) + saveMonitor(); + else + saveApp(); +} + +G_MODULE_EXPORT +void MonListSelect(GtkListBox *list, GtkListBoxRow *row, gpointer userdata) +{ + reloadWlpList(); + reloadMonSettings(); +} + +G_MODULE_EXPORT void MainWindowShow() +{ + reloadAppSettings(); + reloadWlpList(); + + gtk_list_box_select_row( + GTK_LIST_BOX(WID(CONTROL_SIDEBAR)), + gtk_list_box_get_row_at_index(GTK_LIST_BOX(WID(CONTROL_SIDEBAR)), 0) + ); + + gtk_list_box_select_row( + GTK_LIST_BOX(controls[CONTROL_MON_LIST].widget), + gtk_list_box_get_row_at_index( + GTK_LIST_BOX(controls[CONTROL_MON_LIST].widget), 0 + ) + ); + + reloadMonSettings(); +} + +G_MODULE_EXPORT void MainWindowClose() +{ + gtk_widget_set_visible(controls[CONTROL_MAIN_WND].widget, 0); +} + +G_MODULE_EXPORT void SidebarSelect( + GtkListBox *listbox, GtkListBoxRow *row, gpointer userData +) +{ + currentView = gtk_list_box_row_get_index(row); + + char childName[6]; + sprintf(childName, "page%d", currentView); + + gtk_stack_set_visible_child_name( + GTK_STACK(controls[CONTROL_MAIN_STACK].widget), childName + ); +} diff --git a/src/core/wlp.c b/src/core/wlp.c index 2542599..7fded80 100644 --- a/src/core/wlp.c +++ b/src/core/wlp.c @@ -47,7 +47,10 @@ void runWlp() _tcscat(path, TEXT("wlp.exe")); if (CreateProcess(NULL, path, NULL, NULL, FALSE, 0, NULL, NULL, &si, &pi)) + { hWlpProcess = pi.hProcess; + AssignProcessToJobObject(hJob, pi.hProcess); + } else printf("Failed to start a wallpaper subprocess"); diff --git a/src/platform_guard.h b/src/platform_guard.h index 2b1dda8..d10d447 100644 --- a/src/platform_guard.h +++ b/src/platform_guard.h @@ -1,12 +1,16 @@ #ifndef PLATFORM_GUARD_H #define PLATFORM_GUARD_H +#ifdef __WIN32 +#define NTDDI_VERSION 0x0A000000 +#endif + #ifndef __WIN32 #ifndef __LINUX #error "Unsupported platform." -#endif // __LINUX -#endif // __WIN32 +#endif // __LINUX +#endif // __WIN32 -#endif // PLATFORM_GUARD_H +#endif // PLATFORM_GUARD_H diff --git a/src/window_templates/main.glade b/src/window_templates/main.glade index e3147ed..ab31d5e 100644 --- a/src/window_templates/main.glade +++ b/src/window_templates/main.glade @@ -2,186 +2,62 @@ - - - False - Closing Layered WallPaper - False - 480 - 100 - assets/question-svgrepo-com.svg - dialog - False - - - - False - vertical - 2 - - - False - end - - - Yes - True - True - True - - - - True - True - 0 - - - - - No - True - True - True - - - - True - True - 1 - - - - - False - False - 0 - - - - - True - False - - - True - False - assets/question-svgrepo-com.svg - - - False - True - 0 - - - - - True - False - Are you sure, you want to close Layered WallPaper? - - - False - True - 1 - - - - - True - True - 1 - - - - - + 100 + 10000 + 100 + 1 + 10 + + + -10000 + 10000 + 1 + 10 + + + -10000 + 10000 + 1 + 10 + + + 100 10000 + 100 1 10 + 800 + 600 False - Layered WallPaper Settings - False - 800 - 600 + True False - 40 - 40 vertical True False - vertical - - - True - False - 10 - 10 - Layered WallPaper - center - - - - - - - False - True - 0 - - - - - True - False - Enhance your desktop experiance - center - - - - - - False - True - 1 - - - - - False - True - 0 - - - - - True - False - 30 True False - 40 - 40 + center vertical True False - 5 - 15 - Setup your monitors + 10 + Layered WallPaper + @@ -191,136 +67,12 @@ - + True False - - - True - True - - - True - False - - - True - False - 10 - assets/screen-monitor-svgrepo-com.svg - 6 - - - False - True - 0 - - - - - True - False - vertical - - - True - False - HDMI-1 - - - True - True - 0 - - - - - True - False - 1920x1080 - - - False - True - 1 - - - - - True - True - 1 - - - - - - - - - True - True - - - True - False - - - True - False - 10 - assets/screen-monitor-svgrepo-com.svg - 6 - - - False - True - 0 - - - - - True - False - vertical - - - True - False - HDMI-1 - - - - - - True - True - 0 - - - - - True - False - 1920x1080 - - - False - True - 1 - - - - - True - True - 1 - - - - - - + 8 + 8 + Enhance Your desktop experiance False @@ -328,21 +80,6 @@ 1 - - - Edit settings - True - True - True - 10 - - - - False - True - 2 - - True @@ -354,51 +91,27 @@ True False - center - vertical + 10 10 + True - + True True True - + center + center + - + True False - vertical - - - True - False - 20 - assets/image-photo-svgrepo-com.svg - 6 - - - True - True - 0 - - - - - True - False - 15 - 15 - Manage -wallpapers - center - - - False - True - end - 1 - - + 8 + 8 + 8 + 8 + text-x-generic + 3 @@ -409,26 +122,84 @@ wallpapers - + True True True - + center + center + - + True False - vertical - + 8 + 8 + 8 + 8 + document-save + 3 + + + + + False + True + 1 + + + + + False + True + end + 1 + + + + + False + True + 0 + + + + + True + True + True + + + True + False + 8 + 8 + 8 + 8 + browse + + + + True + True + + + True + False + center + 8 + 8 + 8 + 8 + 10 + True False - 20 - assets/settings-svgrepo-com.svg - 6 + video-display - True + False True 0 @@ -437,49 +208,43 @@ wallpapers True False - 15 - 15 - Application -settings - center + Configure monitors + + + False True - end 1 - - False - True - 1 - - + True True - True - True False - vertical + center + 8 + 8 + 8 + 8 + 10 True False - 20 - assets/cross-close-svgrepo-com.svg - 6 + preferences-system - True + False True 0 @@ -488,358 +253,670 @@ settings True False - 15 - 15 - Turn off -Layered WallPaper - center + Application settings + + + + + + False + True + 1 + + + + + + + + + True + True + False + False + + + True + False + center + 8 + 8 + 8 + 8 + 10 + + + True + False + preferences-desktop-wallpaper + + + False + True + 0 + + + + + True + False + Manage wallpapers + + + False True - end 1 - - False - True - 2 - - False - True - end - 1 - - - - - True - True - 1 - - - - - True - False - 20 - - - True - False - 11 - v 1.0.0 - - - False - True - 1 - - - - - Github page - True - True - True - none - https://github.com/jszczerbinsky/lwp - - - False - True - end - 1 - - - - - False - True - end - 2 - - - - - - - False - False - 500 - 250 - - - - - True - False - vertical - - - True - False - center - - - True - False - assets/settings-svgrepo-com.svg - - - False - True - 0 - - - - - True - False - 10 - 10 - Application settings - center - - - - - - False - True - 1 - - - - - False - True - 0 - - - - - - True - False - 20 - 20 - 15 - True - True - - - True - False - start - Target FPS - - - 0 - 0 - - - - - True - False - start - Texture filtering - - - 0 - 1 - - - - - True - False - - Anisotropic - Linear - Nearest-neighbour - - - - 1 - 1 - - - - - True - False - start - Draw on root window (Linux only) - - - 0 - 2 - - - - - True - False - - No - Yes - - - - 1 - 2 + False + True - + True False - - 30 fps - 60 fps - 120 fps - 144 fps - 240 fps - - - - 1 - 0 - - - - - False - True - 1 - - - - - True - False - center - 20 - 20 - 50 - True - - - Apply - True - True - True - - - - False - True - 0 - - - - - Exit - True - True - True - - - - False - True - 1 - - - - - False - True - end - 2 - - - - - - - False - Wallpaper Manager - 800 - 600 - assets/image-photo-svgrepo-com.svg - - - - - True - False - vertical - - - True - False - 10 - 10 - Manage wallpapers - - - - - - False - True - 0 - - - - - True - False + 8 + 8 + 8 + 8 + slide-left-right + + + True + False + vertical + + + True + False + browse + + + + True + True + + + True + False + + + True + False + 10 + video-display + 6 + + + False + True + 0 + + + + + True + False + vertical + + + True + False + HDMI-1 + + + True + True + 0 + + + + + True + False + 1920x1080 + + + False + True + 1 + + + + + True + True + 1 + + + + + + + + + True + True + + + True + False + + + True + False + 10 + video-display + 6 + + + False + True + 0 + + + + + True + False + vertical + + + True + False + HDMI-1 + + + True + True + 0 + + + + + True + False + 1920x1080 + + + False + True + 1 + + + + + True + True + 1 + + + + + + + + + True + True + 0 + + + + + + True + False + 10 + 10 + 10 + 10 + 10 + True + + + True + False + Wallpaper + + + 2 + 0 + + + + + True + False + Offset X + + + 0 + 1 + + + + + True + False + Offset Y + + + 0 + 2 + + + + + True + False + 0 + + Wallpaper 1 + + + + 3 + 0 + 2 + + + + + True + False + Width + + + 2 + 1 + + + + + True + False + Height + + + 2 + 2 + + + + + True + True + WidthAdjustment + + + + 3 + 1 + + + + + True + True + 1 + HeightAdjustment + 1 + + + + 3 + 2 + + + + + True + True + 1 + OffsetXAdjustment + 1 + + + 1 + 1 + + + + + True + True + 1 + OffsetYAdjustment + 1 + + + 1 + 2 + + + + + True + False + Active + + + 0 + 0 + + + + + True + True + center + center + + + 1 + 0 + + + + + True + False + + + True + False + 7 + zoom-best-fit + + + False + True + 0 + + + + + True + True + center + center + 8 + True + + + False + True + 1 + + + + + 4 + 1 + 2 + + + + + False + True + end + 1 + + + + + page0 + page2 + + + + + True + False + vertical + + + + True + False + 15 + True + + + True + False + start + Target FPS + + + 0 + 0 + + + + + True + False + start + Texture filtering + + + 0 + 1 + + + + + True + False + + Anisotropic + Linear + Nearest-neighbour + + + + 1 + 1 + + + + + True + False + + 30 fps + 60 fps + 75 fps + 90 fps + 120 fps + 144 fps + 165 fps + 240 fps + 360 fps + + + + 1 + 0 + + + + + True + False + start + Unfocused monitor behaviour + + + 0 + 2 + + + + + True + False + + Come back + Clamp + + + + 1 + 2 + + + + + True + False + start + Target point + + + 0 + 3 + + + + + True + False + + Mouse + Focused window + + + + 1 + 3 + + + + + False + True + 0 + + + + + True + True + True + center + + + + True + False + center + 30 + 30 + 10 + 10 + 10 + + + True + False + application-exit + + + False + True + 0 + + + + + True + False + Turn off + + + + + + False + True + 1 + + + + + + + False + True + end + 1 + + + + + page1 + page1 + 1 + + + + + True + True + + - False + True True - 1 + 2 True False - center + 10 - - Add + True - True - True + False + 11 + v 1.0.0 False True - 0 + 1 - - Remove + + Github page True True True + none + https://github.com/jszczerbinsky/lwp False True + end 1 @@ -848,267 +925,38 @@ Layered WallPaper False True end - 2 + 3 - - 10000 - 1 - 10 - - - -10000 - 10000 - 1 - 10 - - - -10000 - 10000 - 1 - 10 - - + + False - Monitor Settings - 600 - 260 - assets/settings-svgrepo-com.svg - - + - + True - False - vertical + True + 10 + 10 + 10 + 10 + in + 800 + 600 - + True - False - center - - - True - False - assets/screen-monitor-svgrepo-com.svg - - - False - True - 0 - - - - - True - False - 10 - 10 - Monitor name - center - - - - - - False - True - 1 - - + True + False + 10 + 10 + 10 + 10 + textbuffer1 - - False - True - 0 - - - - - - True - False - 20 - 20 - 15 - True - - - True - False - 0 - - - 1 - 0 - 3 - - - - - True - False - Wallpaper - - - 0 - 0 - - - - - True - False - X position - - - 0 - 1 - - - - - True - False - Y position - - - 0 - 2 - - - - - True - False - Height - - - 2 - 2 - - - - - True - False - Width - - - 2 - 1 - - - - - True - True - 6 - 1 - number - XPosAdjustment - - - 1 - 1 - - - - - True - True - 6 - 1 - number - WidthAdjustment - - - 3 - 1 - - - - - True - True - 6 - 1 - number - HeightAdjustment - - - 3 - 2 - - - - - True - True - 6 - 1 - number - YPosAdjustment - - - 1 - 2 - - - - - False - True - 1 - - - - - True - False - center - 20 - 20 - 50 - True - - - Apply - True - True - True - - - - False - True - 0 - - - - - Exit - True - True - True - - - - False - True - 1 - - - - - False - True - end - 2 - diff --git a/src/wlp/CMakeLists.txt b/src/wlp/CMakeLists.txt index 8055a49..9dccd82 100644 --- a/src/wlp/CMakeLists.txt +++ b/src/wlp/CMakeLists.txt @@ -7,8 +7,9 @@ set(_SOURCE_FILES ../common/config.c ../common/monitorScanner.c ../common/wallpaperScanner.c + ../common/debug.c main.c - debug.c + targetPoint.c render.c window.c ) @@ -47,6 +48,11 @@ if (_UNAME STREQUAL "LINUX") list(APPEND _LIBS ${X11_LIBRARIES}) endif() +if (_UNAME STREQUAL "WIN32") + # Shcore dependency + list(APPEND _LIBS "-lShcore") +endif() + option(LWP_INSTALL_LAUNCHD "Launch lwp on login (MacOSX only)" OFF) # Main executable diff --git a/src/wlp/debug.c b/src/wlp/debug.c deleted file mode 100644 index 5e51f3a..0000000 --- a/src/wlp/debug.c +++ /dev/null @@ -1,40 +0,0 @@ -#include -#include -#include - -#include "main.h" - -void lwpLog(int type, const char *str, ...) -{ - char path[PATH_MAX]; - getLogPath(path); - - FILE *file = fopen(path, "a"); - - char *typePrefix; - - switch (type) - { - case LOG_ERROR: - typePrefix = "ERROR"; - break; - case LOG_INFO: - typePrefix = "INFO"; - break; - case LOG_WARNING: - typePrefix = "WARNING"; - break; - } - - fprintf(file, "%s: ", typePrefix); - - va_list args; - va_start(args, str); - vfprintf(file, str, args); - va_end(args); - - fprintf(file, "\n"); - - fclose(file); -} - diff --git a/src/wlp/main.c b/src/wlp/main.c index b7c5196..c1885d9 100644 --- a/src/wlp/main.c +++ b/src/wlp/main.c @@ -1,13 +1,17 @@ #include "main.h" -#include "../platform_guard.h" - -static App app; +static App app = {0}; static void atExit() { +#ifdef __LINUX + printlog(LOG_INFO, "Closing X11 display..."); + if (app.display) XCloseDisplay(app.display); +#endif + for (int i = 0; i < app.monitorsCount; i++) { + printlog(LOG_INFO, "Freeing monitor %d...", i); Monitor *m = app.monitors + i; if (m->tex) SDL_DestroyTexture(m->tex); if (m->wlp.tex) SDL_DestroyTexture(m->wlp.tex); @@ -16,23 +20,29 @@ static void atExit() SDL_DestroyTexture(m->wlp.layers[l].tex); free(m->wlp.layers); + if (m->renderer) SDL_DestroyRenderer(m->renderer); + if (m->window) SDL_DestroyWindow(m->window); + m++; } - free(app.monitors); - if (app.renderer) SDL_DestroyRenderer(app.renderer); - if (app.window) SDL_DestroyWindow(app.window); + free(app.monitors); + printlog(LOG_INFO, "Quitting SDL2..."); SDL_Quit(); + + printlog(LOG_INFO, "Done"); } void exitSignalHandler(int s) { - lwpLog(LOG_INFO, "Terminating..."); + printlog(LOG_INFO, "Terminating..."); exit(0); } -void initWallpaper(App *app, Monitor *m, WallpaperInfo *wallpapers, int wallpapersCount) +void initWallpaper( + App *app, Monitor *m, WallpaperInfo *wallpapers, int wallpapersCount +) { MonitorInfo *mi = &m->info; @@ -46,15 +56,19 @@ void initWallpaper(App *app, Monitor *m, WallpaperInfo *wallpapers, int wallpape if (!loadWallpaperConfig(m->wlp.info.dirPath, &m->wlp.info.config)) { - lwpLog(LOG_WARNING, "Could not load the wallpaper config"); + printlog(LOG_WARNING, "Could not load the wallpaper config"); } else { Wallpaper *wallpaper = &m->wlp; - lwpLog(LOG_INFO, "Initializing wallpaper %s...", wallpaper->info.name); - lwpLog(LOG_INFO, "Layers count: %d", wallpaper->info.config.layersCount); - lwpLog( + printlog( + LOG_INFO, "Initializing wallpaper %s...", wallpaper->info.name + ); + printlog( + LOG_INFO, "Layers count: %d", wallpaper->info.config.layersCount + ); + printlog( LOG_INFO, "Repeat X Y: %d %d", wallpaper->info.config.repeatX, @@ -62,25 +76,34 @@ void initWallpaper(App *app, Monitor *m, WallpaperInfo *wallpapers, int wallpape ); m->tex = SDL_CreateTexture( - app->renderer, + m->renderer, SDL_PIXELFORMAT_ARGB8888, SDL_TEXTUREACCESS_TARGET, - mi->bounds.w, - mi->bounds.h + mi->clientBounds.w, + mi->clientBounds.h ); if (m->tex == NULL) - lwpLog(LOG_ERROR, "Failed creating a texture for the monitor: %s", SDL_GetError()); - - wallpaper->layers = malloc(sizeof(Layer) * wallpaper->info.config.layersCount); - wallpaper->tex = SDL_CreateTexture( - app->renderer, + printlog( + LOG_ERROR, + "Failed creating a texture for the monitor: %s", + SDL_GetError() + ); + + wallpaper->layers = + malloc(sizeof(Layer) * wallpaper->info.config.layersCount); + wallpaper->tex = SDL_CreateTexture( + m->renderer, SDL_PIXELFORMAT_ARGB8888, SDL_TEXTUREACCESS_TARGET, mi->config.wlpBounds.w, mi->config.wlpBounds.h ); if (wallpaper->tex == NULL) - lwpLog(LOG_ERROR, "Failed creating a texture for the monitor: %s", SDL_GetError()); + printlog( + LOG_ERROR, + "Failed creating a texture for the monitor: %s", + SDL_GetError() + ); for (int l = 0; l < wallpaper->info.config.layersCount; l++) { @@ -88,7 +111,7 @@ void initWallpaper(App *app, Monitor *m, WallpaperInfo *wallpapers, int wallpape snprintf(path, PATH_MAX, "%s/%d.bmp", wallpaper->info.dirPath, l + 1); SDL_Surface *surf = SDL_LoadBMP(path); - if (!surf) lwpLog(LOG_ERROR, "File %s not found", path); + if (!surf) printlog(LOG_ERROR, "File %s not found", path); if (l == 0) { @@ -96,9 +119,15 @@ void initWallpaper(App *app, Monitor *m, WallpaperInfo *wallpapers, int wallpape wallpaper->originalH = surf->h; } - wallpaper->layers[l].tex = SDL_CreateTextureFromSurface(app->renderer, surf); + wallpaper->layers[l].tex = + SDL_CreateTextureFromSurface(m->renderer, surf); if (wallpaper->tex == NULL) - lwpLog(LOG_ERROR, "Failed creating a texture for the layer %d: %s", l, SDL_GetError()); + printlog( + LOG_ERROR, + "Failed creating a texture for the layer %d: %s", + l, + SDL_GetError() + ); SDL_FreeSurface(surf); } @@ -108,18 +137,19 @@ void initWallpaper(App *app, Monitor *m, WallpaperInfo *wallpapers, int wallpape break; } } - if (!foundWlp) lwpLog(LOG_WARNING, "Couldn't find the wallpaper. Ignoring..."); + if (!foundWlp) + printlog(LOG_WARNING, "Couldn't find the wallpaper. Ignoring..."); } -int initMonitors(App *app) +void initMonitors(App *app) { MonitorInfo *monitors = scanMonitors(&app->monitorsCount); - app->monitors = malloc(sizeof(Monitor) * app->monitorsCount); + app->monitors = calloc(app->monitorsCount, sizeof(Monitor)); int wallpapersCount; WallpaperInfo *wallpapers = scanWallpapers(&wallpapersCount); - lwpLog(LOG_INFO, "Scanner found %d monitor(s)", app->monitorsCount); + printlog(LOG_INFO, "Scanner found %d monitor(s)", app->monitorsCount); for (int i = 0; i < app->monitorsCount; i++) { @@ -128,18 +158,30 @@ int initMonitors(App *app) MonitorInfo *mi = &app->monitors[i].info; + app->monitors[i].currentPoint.x = 0; + app->monitors[i].currentPoint.y = 0; + if (!loadMonitorConfig(mi->name, &mi->config)) { - lwpLog(LOG_WARNING, "Couldn't find config file for monitor %s. Ignoring...", mi->name); + printlog( + LOG_WARNING, + "Couldn't find config file for monitor %s. Ignoring...", + mi->name + ); } else { - lwpLog(LOG_INFO, "Initializing monitor %d...", i); - lwpLog(LOG_INFO, "Wallpaper: %s", mi->config.wlpName); - lwpLog( - LOG_INFO, "Bounds: %d %d %dx%d", mi->bounds.x, mi->bounds.y, mi->bounds.w, mi->bounds.h + printlog(LOG_INFO, "Initializing monitor %d...", i); + printlog(LOG_INFO, "Wallpaper: %s", mi->config.wlpName); + printlog( + LOG_INFO, + "Bounds: %d %d %dx%d", + mi->clientBounds.x, + mi->clientBounds.y, + mi->clientBounds.w, + mi->clientBounds.h ); - lwpLog( + printlog( LOG_INFO, "Wallpaper destination bounds: %d %d %dx%d", mi->config.wlpBounds.x, @@ -148,7 +190,14 @@ int initMonitors(App *app) mi->config.wlpBounds.h ); - initWallpaper(app, app->monitors + i, wallpapers, wallpapersCount); + if (app->monitors[i].info.config.active) + { + initWindow(app, app->monitors + i); + + initWallpaper(app, app->monitors + i, wallpapers, wallpapersCount); + } + else + app->monitors[i].aborted = 1; } } @@ -158,6 +207,12 @@ int initMonitors(App *app) int main(int argc, char *argv[]) { + clearlog(); + +#ifdef __WIN32 + SetProcessDPIAware(); +#endif + memset(&app, 0, sizeof(App)); char pidStr[10]; @@ -169,27 +224,28 @@ int main(int argc, char *argv[]) #ifdef __WIN32 signal(SIGTERM, exitSignalHandler); #else - signal(SIGINT, exitSignalHandler); + signal(SIGKILL, exitSignalHandler); #endif - lwpLog(LOG_INFO, "Starting Layered WallPaper"); + printlog(LOG_INFO, "Starting Layered WallPaper"); - lwpLog(LOG_INFO, "Loading app config"); + printlog(LOG_INFO, "Loading app config"); loadAppConfig(&app.config); - lwpLog(LOG_INFO, "Initializing SDL"); + printlog(LOG_INFO, "Initializing SDL"); SDL_Init(SDL_INIT_VIDEO | SDL_INIT_EVENTS); SDL_SetHint(SDL_HINT_RENDER_SCALE_QUALITY, app.config.renderQuality); - lwpLog(LOG_INFO, "Initializing window"); - initWindow(&app); - - lwpLog(LOG_INFO, "Initializing monitors"); + printlog(LOG_INFO, "Initializing monitors"); initMonitors(&app); atexit(atExit); - lwpLog(LOG_INFO, "Starting wallpaper loop"); + printlog(LOG_INFO, "Starting wallpaper loop"); + +#ifdef __LINUX + app.display = XOpenDisplay(NULL); +#endif runWallpaperLoop(&app); return 0; diff --git a/src/wlp/main.h b/src/wlp/main.h index cdbe86b..af7bd15 100644 --- a/src/wlp/main.h +++ b/src/wlp/main.h @@ -1,6 +1,8 @@ #ifndef MAIN_H #define MAIN_H +#include "../platform_guard.h" + #ifdef _MSC_VER #define PATH_MAX MAX_PATH #include @@ -23,13 +25,15 @@ #include "../common.h" -#define LOG_ERROR 0 -#define LOG_INFO 1 -#define LOG_WARNING 2 +typedef struct +{ + float x; + float y; +} Point; typedef struct { - SDL_Texture *tex; + SDL_Texture* tex; } Layer; typedef struct @@ -37,29 +41,36 @@ typedef struct WallpaperInfo info; int originalW; int originalH; - SDL_Texture *tex; - Layer *layers; + SDL_Texture* tex; + Layer* layers; } Wallpaper; typedef struct { - MonitorInfo info; - SDL_Texture *tex; - Wallpaper wlp; + MonitorInfo info; + SDL_Texture* tex; + Wallpaper wlp; + SDL_Window* window; + SDL_Renderer* renderer; + Point currentPoint; + int aborted; } Monitor; typedef struct { - AppConfig config; - int monitorsCount; - Monitor *monitors; - SDL_Window *window; - SDL_Renderer *renderer; + AppConfig config; + int monitorsCount; + Monitor* monitors; + +#ifdef __LINUX + Display* display; +#endif + } App; -void lwpLog(int type, const char *str, ...); +void initWindow(App* app, Monitor* monitor); +void runWallpaperLoop(App* app); -void initWindow(App *app); -void runWallpaperLoop(App *app); +void getTargetPoint(App* app, Point* p); #endif // MAIN_H diff --git a/src/wlp/render.c b/src/wlp/render.c index d0ddc5b..2c27b7c 100644 --- a/src/wlp/render.c +++ b/src/wlp/render.c @@ -8,152 +8,191 @@ static int lerp(int a, int b, float t) return (int)((float)a + (float)t * ((float)b - (float)a)); } -void runWallpaperLoop(App *app) +static float clamp(float a, float min, float max) { - int quit = 0; - - SDL_Event event; + if (a < min) return min; + if (a > max) return max; + return a; +} - int mx = 0; - int my = 0; +static void lerpTargetPoint(Point* p, Point* target, float dT) +{ + p->x = lerp(p->x, target->x, dT * 4); // 4: smooth + p->y = lerp(p->y, target->y, dT * 4); +} - while (!quit) - { - static int currentX = 0; - static int currentY = 0; +static void getRelativeTargetPoint( + Point* dest, const Point* globalTargetPoint, const Monitor* m +) +{ + dest->x = globalTargetPoint->x - m->info.clientBounds.x; + dest->y = globalTargetPoint->y - m->info.clientBounds.y; +} - static int lastTicks = 0; +static void clampTargetPoint(Point* p, Monitor* m) +{ + p->x = clamp(p->x, 0, m->info.clientBounds.w); + p->y = clamp(p->y, 0, m->info.clientBounds.h); +} - int ticks = SDL_GetTicks(); - float dT = (ticks - lastTicks) / 1000.0f; - lastTicks = ticks; +static void comeBackTargetPoint(Point* p, Monitor* m) +{ + if (p->x < 0 || p->x > m->info.clientBounds.w || p->y < 0 || + p->y > m->info.clientBounds.h) + { + p->x = m->info.clientBounds.w / 2; + p->y = m->info.clientBounds.h / 2; + } +} -#ifdef __WIN32 - POINT mPos; - GetCursorPos(&mPos); - mx = mPos.x - GetSystemMetrics(SM_XVIRTUALSCREEN); - my = mPos.y - GetSystemMetrics(SM_YVIRTUALSCREEN); -#else - SDL_GetGlobalMouseState(&mx, &my); -#endif +static float distanceSquared(const Point* p, const Point* q) +{ + return (p->x - q->x) * (p->x - q->x) + (p->y - q->y) * (p->y - q->y); +} - while (SDL_PollEvent(&event)) - if (event.type == SDL_QUIT) quit = 1; +static void renderMonitor( + App* app, Monitor* monitor, const Point* globalTargetPoint, float dT, + int firstRender +) +{ + if (!monitor->info.config.loaded || !monitor->wlp.info.config.loaded) return; - currentX = lerp(currentX, mx, dT * 4); // 4: smooth - currentY = lerp(currentY, my, dT * 4); + Point targetPoint; + getRelativeTargetPoint(&targetPoint, globalTargetPoint, monitor); - for (int m = 0; m < app->monitorsCount; m++) - { - if (!app->monitors[m].info.config.loaded || !app->monitors[m].wlp.info.config.loaded) - continue; + if (app->config.unfocusedComeback) + comeBackTargetPoint(&targetPoint, monitor); + else + clampTargetPoint(&targetPoint, monitor); - int relativeCurrentX = currentX - app->monitors[m].info.bounds.x; - int relativeCurrentY = currentY - app->monitors[m].info.bounds.y; + lerpTargetPoint(&monitor->currentPoint, &targetPoint, dT); - if (relativeCurrentX < 0) relativeCurrentX = 0; - if (relativeCurrentY < 0) relativeCurrentY = 0; - if (relativeCurrentX > app->monitors[m].info.bounds.w) - relativeCurrentX = app->monitors[m].info.bounds.w; - if (relativeCurrentY > app->monitors[m].info.bounds.h) - relativeCurrentY = app->monitors[m].info.bounds.h; + if (distanceSquared(&monitor->currentPoint, &targetPoint) < 1 && !firstRender) + return; - if (SDL_SetRenderTarget(app->renderer, app->monitors[m].wlp.tex) != 0) - { - lwpLog(LOG_ERROR, "Error setting the renderer target: %s", SDL_GetError()); - quit = 1; - } - SDL_RenderClear(app->renderer); + if (SDL_SetRenderTarget(monitor->renderer, monitor->wlp.tex) != 0) + { + printlog( + LOG_ERROR, "Error setting the renderer target: %s", SDL_GetError() + ); + monitor->aborted = 1; + return; + } + SDL_RenderClear(monitor->renderer); - for (int i = 0; i < app->monitors[m].wlp.info.config.layersCount; i++) + for (int i = 0; i < monitor->wlp.info.config.layersCount; i++) + { + SDL_Rect src = { + .x = 0, + .y = 0, + .w = monitor->wlp.originalW, + .h = monitor->wlp.originalH, + }; + + int x = + -((monitor->currentPoint.x - monitor->info.clientBounds.w / 2) * + monitor->wlp.info.config.layerConfigs[i].sensitivityX); + int y = + -((monitor->currentPoint.y - monitor->info.clientBounds.h / 2) * + monitor->wlp.info.config.layerConfigs[i].sensitivityY); + + for (int k = -monitor->wlp.info.config.repeatY; + k <= monitor->wlp.info.config.repeatY; + k++) + { + for (int j = -monitor->wlp.info.config.repeatX; + j <= monitor->wlp.info.config.repeatX; + j++) { - SDL_Rect src = { - .x = 0, - .y = 0, - .w = app->monitors[m].wlp.originalW, - .h = app->monitors[m].wlp.originalH, + SDL_Rect dest = { + .x = x + j * monitor->info.config.wlpBounds.w, + .y = y + k * monitor->info.config.wlpBounds.h, + .w = monitor->info.config.wlpBounds.w, + .h = monitor->info.config.wlpBounds.h, }; - int x = - -((relativeCurrentX - app->monitors[m].info.bounds.w / 2) * - app->monitors[m].wlp.info.config.layerConfigs[i].sensitivityX); - int y = - -((relativeCurrentY - app->monitors[m].info.bounds.h / 2) * - app->monitors[m].wlp.info.config.layerConfigs[i].sensitivityY); - - for (int k = -app->monitors[m].wlp.info.config.repeatY; - k <= app->monitors[m].wlp.info.config.repeatY; - k++) + if (SDL_RenderCopy( + monitor->renderer, monitor->wlp.layers[i].tex, &src, &dest + ) != 0) { - for (int j = -app->monitors[m].wlp.info.config.repeatX; - j <= app->monitors[m].wlp.info.config.repeatX; - j++) - { - SDL_Rect dest = { - .x = x + j * app->monitors[m].info.config.wlpBounds.w, - .y = y + k * app->monitors[m].info.config.wlpBounds.h, - .w = app->monitors[m].info.config.wlpBounds.w, - .h = app->monitors[m].info.config.wlpBounds.h, - }; - - if (SDL_RenderCopy(app->renderer, app->monitors[m].wlp.layers[i].tex, &src, &dest) != 0) - { - lwpLog(LOG_ERROR, "Error rendering copy: %s", SDL_GetError()); - quit = 1; - } - } + printlog(LOG_ERROR, "Error rendering copy: %s", SDL_GetError()); + monitor->aborted = 1; } } + } + } - if (SDL_SetRenderTarget(app->renderer, app->monitors[m].tex) != 0) - { - lwpLog(LOG_ERROR, "Error setting the renderer target: %s", SDL_GetError()); - quit = 1; - } + if (SDL_SetRenderTarget(monitor->renderer, monitor->tex) != 0) + { + printlog( + LOG_ERROR, "Error setting the renderer target: %s", SDL_GetError() + ); + monitor->aborted = 1; + } - SDL_Rect src = { - .x = 0, - .y = 0, - .w = app->monitors[m].info.config.wlpBounds.w, - .h = app->monitors[m].info.config.wlpBounds.h, - }; - - SDL_Rect dest = { - .x = app->monitors[m].info.config.wlpBounds.x, - .y = app->monitors[m].info.config.wlpBounds.y, - .w = app->monitors[m].info.config.wlpBounds.w, - .h = app->monitors[m].info.config.wlpBounds.h, - }; - - if (SDL_RenderCopy(app->renderer, app->monitors[m].wlp.tex, &src, &dest) != 0) - { - lwpLog(LOG_ERROR, "Error rendering copy: %s", SDL_GetError()); - quit = 1; - } + SDL_Rect src = { + .x = 0, + .y = 0, + .w = monitor->info.config.wlpBounds.w, + .h = monitor->info.config.wlpBounds.h, + }; + + SDL_Rect dest = { + .x = monitor->info.config.wlpBounds.x, + .y = monitor->info.config.wlpBounds.y, + .w = monitor->info.config.wlpBounds.w, + .h = monitor->info.config.wlpBounds.h, + }; + + if (SDL_RenderCopy(monitor->renderer, monitor->wlp.tex, &src, &dest) != 0) + { + printlog(LOG_ERROR, "Error rendering copy: %s", SDL_GetError()); + monitor->aborted = 1; + } - SDL_SetRenderTarget(app->renderer, NULL); + SDL_SetRenderTarget(monitor->renderer, NULL); - SDL_Rect finalSrc = { - .x = 0, - .y = 0, - .w = app->monitors[m].info.bounds.w, - .h = app->monitors[m].info.bounds.h, - }; + if (SDL_RenderCopy(monitor->renderer, monitor->tex, NULL, NULL) != 0) + { + printlog(LOG_ERROR, "Error rendering copy: %s", SDL_GetError()); + monitor->aborted = 1; + } - SDL_Rect finalDest = { - .x = app->monitors[m].info.bounds.x, - .y = app->monitors[m].info.bounds.y, - .w = app->monitors[m].info.bounds.w, - .h = app->monitors[m].info.bounds.h, - }; + SDL_RenderPresent(monitor->renderer); + SDL_Delay(1000 / app->config.targetFps); +} - if (SDL_RenderCopy(app->renderer, app->monitors[m].tex, &finalSrc, &finalDest) != 0) - { - lwpLog(LOG_ERROR, "Error rendering copy: %s", SDL_GetError()); - quit = 1; - } +static void getInput(int* quit) +{ + SDL_Event event; + + while (SDL_PollEvent(&event)) + if (event.type == SDL_QUIT) (*quit) = 1; +} + +void runWallpaperLoop(App* app) +{ + Point targetPoint; + + int firstRender = 1; + int quit = 0; + while (!quit) + { + static int lastTicks = 0; + + int ticks = SDL_GetTicks(); + float dT = (ticks - lastTicks) / 1000.0f; + lastTicks = ticks; + + getInput(&quit); + + getTargetPoint(app, &targetPoint); + + for (int m = 0; m < app->monitorsCount; m++) + { + if (!app->monitors[m].aborted) + renderMonitor(app, app->monitors + m, &targetPoint, dT, firstRender); } - SDL_RenderPresent(app->renderer); - SDL_Delay(1000 / app->config.targetFps); + firstRender = 0; } } diff --git a/src/wlp/targetPoint.c b/src/wlp/targetPoint.c new file mode 100644 index 0000000..98dd075 --- /dev/null +++ b/src/wlp/targetPoint.c @@ -0,0 +1,46 @@ +#include "main.h" + +void getTargetPoint(App* app, Point* p) +{ + if (app->config.wndTargetPoint) + { +#ifdef __WIN32 + HWND focusedWnd = GetForegroundWindow(); + + if (focusedWnd) + { + RECT rect; + GetWindowRect(focusedWnd, &rect); + + p->x = rect.left + (rect.right - rect.left) / 2; + p->y = rect.top + (rect.bottom - rect.top) / 2; + } +#else + Window wnd; + int revertTo; + XGetInputFocus(app->display, &wnd, &revertTo); + + int x, y; + unsigned int w, h, bw, bh; + Window rootWnd; + XGetGeometry(app->display, wnd, &rootWnd, &x, &y, &w, &h, &bw, &bh); + + p->x = x; + p->y = y; +#endif + } + else + { +#ifdef __WIN32 + POINT mPos; + GetCursorPos(&mPos); + p->x = mPos.x - GetSystemMetrics(SM_XVIRTUALSCREEN); + p->y = mPos.y - GetSystemMetrics(SM_YVIRTUALSCREEN); +#else + int x, y; + SDL_GetGlobalMouseState(&x, &y); + p->x = x; + p->y = y; +#endif + } +} diff --git a/src/wlp/window.c b/src/wlp/window.c index c160103..e9c653f 100644 --- a/src/wlp/window.c +++ b/src/wlp/window.c @@ -32,96 +32,108 @@ static BOOL CALLBACK getIconWorkerw(HWND hWnd, LPARAM lParam) #endif -void initWindow(App *app) +void initWindow(App *app, Monitor *monitor) { #ifdef __WIN32 - app->window = - SDL_CreateWindow("Parallax wallpaper", 0, 0, 0, 0, SDL_WINDOW_OPENGL | SDL_WINDOW_HIDDEN); - if (app->window == NULL) lwpLog(LOG_ERROR, "%s", SDL_GetError()); + monitor->window = SDL_CreateWindow( + "Parallax wallpaper", 0, 0, 0, 0, SDL_WINDOW_OPENGL | SDL_WINDOW_HIDDEN + ); + if (monitor->window == NULL) printlog(LOG_ERROR, "%s", SDL_GetError()); SDL_SysWMinfo sysWmInfo; SDL_VERSION(&sysWmInfo.version) - SDL_GetWindowWMInfo(app->window, &sysWmInfo); + SDL_GetWindowWMInfo(monitor->window, &sysWmInfo); HWND hWindow = sysWmInfo.info.win.window; HWND progman = FindWindow("Progman", NULL); iconWorkerw = progman; - SendMessageTimeout(progman, 0x052C, NULL, NULL, SMTO_NORMAL, 1000, NULL); - if (!FindWindowEx(progman, NULL, "SHELLDLL_DefView", NULL)) EnumWindows(getIconWorkerw, NULL); + SendMessageTimeout(progman, 0x052C, 0, 0, SMTO_NORMAL, 1000, NULL); + if (!FindWindowEx(progman, NULL, "SHELLDLL_DefView", NULL)) + EnumWindows(getIconWorkerw, 0); HWND wallpaperWorkerw = GetWindow(iconWorkerw, GW_HWNDNEXT); SetParent(hWindow, wallpaperWorkerw); SetWindowLongPtr( - hWindow, GWL_EXSTYLE, WS_EX_LEFT | WS_EX_LTRREADING | WS_EX_RIGHTSCROLLBAR | WS_EX_NOACTIVATE + hWindow, + GWL_EXSTYLE, + WS_EX_LEFT | WS_EX_LTRREADING | WS_EX_RIGHTSCROLLBAR | WS_EX_NOACTIVATE ); SetWindowLongPtr(hWindow, GWL_STYLE, WS_CHILDWINDOW | WS_VISIBLE); SetWindowPos( hWindow, NULL, - 0, - 0, - GetSystemMetrics(SM_CXVIRTUALSCREEN), - GetSystemMetrics(SM_CYVIRTUALSCREEN), + monitor->info.virtualBounds.x, + monitor->info.virtualBounds.y, + monitor->info.virtualBounds.w, + monitor->info.virtualBounds.h, SWP_NOZORDER | SWP_NOACTIVATE | SWP_SHOWWINDOW ); #else - if (!app->config.drawOnRootWindow) - { - Display *display = XOpenDisplay(NULL); - XCloseDisplay(display); - - app->window = SDL_CreateWindow( - "Layered WallPaper", - 0, - 0, - DisplayWidth(display, 0), - DisplayHeight(display, 0), - SDL_WINDOW_OPENGL - ); + Display *display; - SDL_SysWMinfo wmInfo; - SDL_GetVersion(&wmInfo.version); - SDL_GetWindowWMInfo(app->window, &wmInfo); - - Window xWnd = wmInfo.info.x11.window; - display = wmInfo.info.x11.display; - - Atom atomType = XInternAtom(display, "_NET_WM_WINDOW_TYPE", 0); - Atom atomDesktop = XInternAtom(display, "_NET_WM_WINDOW_TYPE_DESKTOP", 0); - XChangeProperty( - display, - xWnd, - atomType, - XA_ATOM, - 32, - PropModeReplace, - (const unsigned char *)&atomDesktop, - 1 - ); + monitor->window = SDL_CreateWindow( + "Layered WallPaper", + monitor->info.virtualBounds.x, + monitor->info.virtualBounds.y, + monitor->info.virtualBounds.w, + monitor->info.virtualBounds.h, + SDL_WINDOW_OPENGL + ); - Window rootWindow = RootWindow(display, DefaultScreen(display)); + SDL_SysWMinfo wmInfo; + SDL_GetVersion(&wmInfo.version); + SDL_GetWindowWMInfo(monitor->window, &wmInfo); + + Window xWnd = wmInfo.info.x11.window; + display = wmInfo.info.x11.display; + + Atom atomType = XInternAtom(display, "_NET_WM_WINDOW_TYPE", 0); + Atom atomDesktop = XInternAtom(display, "_NET_WM_WINDOW_TYPE_DESKTOP", 0); + XChangeProperty( + display, + xWnd, + atomType, + XA_ATOM, + 32, + PropModeReplace, + (const unsigned char *)&atomDesktop, + 1 + ); - XReparentWindow(display, xWnd, rootWindow, 0, 0); + Window rootWindow = RootWindow(display, DefaultScreen(display)); - XSync(display, 0); - } - else - { - Display *display = XOpenDisplay(NULL); - Window rootWindow = RootWindow(display, DefaultScreen(display)); - app->window = SDL_CreateWindowFrom((void *)rootWindow); - XCloseDisplay(display); - } + XReparentWindow( + display, + xWnd, + rootWindow, + monitor->info.virtualBounds.x, + monitor->info.virtualBounds.y + ); + + XSync(display, 0); #endif - if (app->window == NULL) lwpLog(LOG_ERROR, "Failed to initialize window: %s", SDL_GetError()); + if (monitor->window == NULL) + printlog( + LOG_ERROR, + "Failed to initialize window for monitor %s: %s", + monitor->info.name, + SDL_GetError() + ); - app->renderer = - SDL_CreateRenderer(app->window, -1, SDL_RENDERER_ACCELERATED | SDL_RENDERER_PRESENTVSYNC); - if (app->renderer == NULL) lwpLog(LOG_ERROR, "Failed to initialize renderer: %s", SDL_GetError()); + monitor->renderer = SDL_CreateRenderer( + monitor->window, -1, SDL_RENDERER_ACCELERATED | SDL_RENDERER_PRESENTVSYNC + ); + if (monitor->renderer == NULL) + printlog( + LOG_ERROR, + "Failed to initialize renderer for monitor %s: %s", + monitor->info.name, + SDL_GetError() + ); }