From c47ee5da84b2649451c54341c3b76c8b8a67418b Mon Sep 17 00:00:00 2001 From: omega ui Date: Mon, 8 Jan 2024 17:11:58 +0530 Subject: [PATCH] =?UTF-8?q?=E2=9A=A1=20Support=20for=20Multi-monitor=20set?= =?UTF-8?q?ups.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - This fixes #1. --- AppImageBuilder.yml | 2 +- debian/debian.yaml | 2 +- .../dialogs/power_mode_settings.dart | 74 +++++++++++++++++++ lib/constants/meta_info.dart | 2 +- lib/core/storage/storage.dart | 13 ++++ lib/core/utils.dart | 11 +++ linux/my_application.cc | 45 ++++++++++- pubspec.yaml | 2 +- 8 files changed, 144 insertions(+), 7 deletions(-) diff --git a/AppImageBuilder.yml b/AppImageBuilder.yml index 46e54ea..759f56c 100644 --- a/AppImageBuilder.yml +++ b/AppImageBuilder.yml @@ -11,7 +11,7 @@ AppDir: id: org.omegaui.cliptopia name: Cliptopia icon: app-icon - version: 1.0.0+4 + version: 1.0.0+5 exec: cliptopia exec_args: $@ apt: diff --git a/debian/debian.yaml b/debian/debian.yaml index d990162..37cb52b 100644 --- a/debian/debian.yaml +++ b/debian/debian.yaml @@ -5,7 +5,7 @@ flutter_app: control: Package: Cliptopia - Version: 1.0.0+4 + Version: 1.0.0+5 Architecture: amd64 Essential: no Priority: optional diff --git a/lib/app/powermode/presentation/dialogs/power_mode_settings.dart b/lib/app/powermode/presentation/dialogs/power_mode_settings.dart index 02d44c4..cec47b0 100644 --- a/lib/app/powermode/presentation/dialogs/power_mode_settings.dart +++ b/lib/app/powermode/presentation/dialogs/power_mode_settings.dart @@ -4,7 +4,9 @@ import 'package:cliptopia/config/assets/app_artworks.dart'; import 'package:cliptopia/config/assets/app_icons.dart'; import 'package:cliptopia/config/themes/app_theme.dart'; import 'package:cliptopia/constants/meta_info.dart'; +import 'package:cliptopia/core/argument_handler.dart'; import 'package:cliptopia/core/storage/storage.dart'; +import 'package:cliptopia/core/utils.dart'; import 'package:flutter/material.dart'; import 'package:gap/gap.dart'; import 'package:url_launcher/url_launcher_string.dart'; @@ -227,6 +229,78 @@ class _PowerModeSettingsState extends State { ), ), const Gap(25), + if (isMultiMonitorSetup()) ...[ + Padding( + padding: const EdgeInsets.only( + left: 36, + right: 36, + ), + child: SizedBox( + height: 50, + child: Row( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + Image.asset( + AppIcons.desktop, + width: 48, + height: 48, + fit: BoxFit.fitWidth, + ), + const SizedBox(width: 11), + Column( + mainAxisSize: MainAxisSize.min, + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text( + "Choose the target monitor${ArgumentHandler.isDebugMode() ? " (In Test Mode)" : ""}", + style: AppTheme.fontSize(16).makeBold(), + ), + const SizedBox(height: 5), + Text( + "Select the monitor on which the power mode window should appear", + style: AppTheme.fontSize(14), + ), + ], + ), + Expanded( + child: Row( + mainAxisAlignment: MainAxisAlignment.end, + children: [ + SizedBox( + width: 40, + child: DropdownButton( + items: List.generate(getMonitorCount(), + (index) => index + 1) + .map( + (e) => DropdownMenuItem( + value: e, + child: Text( + "$e", + style: AppTheme.fontSize(14) + .makeBold(), + ), + ), + ) + .toList(), + value: + Storage.getSelectedMonitorIndex() + 1, + onChanged: (int? value) { + setState(() { + Storage.setSelectedMonitorIndex( + (value ?? 1) - 1); + }); + }, + ), + ), + ], + ), + ), + ], + ), + ), + ), + ], + const Gap(25), Option( title: "Keep the images hidden until triggered", description: diff --git a/lib/constants/meta_info.dart b/lib/constants/meta_info.dart index 928e025..6f672ff 100644 --- a/lib/constants/meta_info.dart +++ b/lib/constants/meta_info.dart @@ -3,7 +3,7 @@ import 'package:cliptopia/core/utils.dart'; class MetaInfo { MetaInfo._(); - static String get version => "v1.0.0+4-beta"; + static String get version => "v1.0.0+5-beta"; static String get daemonCompatibleVersion => "v0.0.3"; static const daemonDownloadUrl = "https://github.com/omegaui/cliptopia_daemon/raw/master/cliptopia-daemon"; diff --git a/lib/core/storage/storage.dart b/lib/core/storage/storage.dart index 5cedd57..2507493 100644 --- a/lib/core/storage/storage.dart +++ b/lib/core/storage/storage.dart @@ -10,6 +10,8 @@ import 'package:flutter/services.dart'; class Storage { static late final File copyScript; static late final File commandExecutorScript; + static final File monitorIndexFile = + File(combineHomePath(['.config', 'cliptopia', 'monitor.index'])); static late final JsonConfigurator _storage; Storage._(); @@ -74,6 +76,17 @@ class Storage { static bool isSensitivityOn() { return get(StorageKeys.sensitivity, fallback: false); } + + static int getSelectedMonitorIndex() { + if (!monitorIndexFile.existsSync()) { + return 0; + } + return int.tryParse(monitorIndexFile.readAsStringSync()) ?? 0; + } + + static void setSelectedMonitorIndex(int index) { + monitorIndexFile.writeAsStringSync("$index"); + } } class TempStorage { diff --git a/lib/core/utils.dart b/lib/core/utils.dart index 806b668..306da9b 100644 --- a/lib/core/utils.dart +++ b/lib/core/utils.dart @@ -45,6 +45,17 @@ String _pgrep(pattern) { return Process.runSync('pgrep', ['-x', pattern]).stdout; } +int getMonitorCount() { + if (ArgumentHandler.isDebugMode()) { + return 3; // for enabling the full settings interface + } + return WidgetsBinding.instance.platformDispatcher.views.length; +} + +bool isMultiMonitorSetup() { + return getMonitorCount() > 1; +} + bool isDaemonAlive() { final daemonProcess = _pgrep('cliptopia-daemon'); final devProcess = _pgrep('dart:cliptopia_'); diff --git a/linux/my_application.cc b/linux/my_application.cc index 7a1cf24..7e7b1d4 100644 --- a/linux/my_application.cc +++ b/linux/my_application.cc @@ -1,4 +1,8 @@ #include "my_application.h" +#include +#include +#include +#include #include #include @@ -12,6 +16,39 @@ static gchar** global_argv = NULL; + +int readMonitorIndex() { + // Get the user's home directory + const char *homeDir = getenv("HOME"); + if (homeDir == NULL) { + fprintf(stderr, "Error: HOME environment variable not set.\n"); + return 0; + } + + // Create the full path to the monitor configuration file + char configFile[256]; + snprintf(configFile, sizeof(configFile), "%s/.config/cliptopia/monitor.index", homeDir); + + // Open the file for reading + FILE *file = fopen(configFile, "r"); + if (file == NULL) { + fprintf(stderr, "Error opening file: %s\n", configFile); + return 0; + } + + // Read the integer from the file + int monitorIndex = 0; + if (fscanf(file, "%d", &monitorIndex) != 1) { + fprintf(stderr, "Error reading monitor index from file: %s\n", configFile); + fclose(file); + } + + // Close the file + fclose(file); + + return monitorIndex; +} + bool hasFlag(const char* flag, int argc, char** argv) { for (int i = 1; i < argc; ++i) { if (argv[i] != NULL && g_strcmp0(argv[i], flag) == 0) { @@ -66,11 +103,13 @@ static void my_application_activate(GApplication* application) { gtk_window_set_resizable(window, FALSE); if (global_argv != NULL && - hasFlag("--silent", length, global_argv) && - hasFlag("--power", length, global_argv)) { + hasFlag("--silent", length, global_argv) && + hasFlag("--power", length, global_argv)) { + // Read monitor index from the monitor config file + int monitorIndex = readMonitorIndex(); GdkScreen* screen = gtk_window_get_screen(window); GdkRectangle monitor_rect; - gdk_screen_get_monitor_geometry(screen, 0, &monitor_rect); + gdk_screen_get_monitor_geometry(screen, monitorIndex, &monitor_rect); gtk_window_set_default_size(window, monitor_rect.width, monitor_rect.height); } else { gtk_window_set_default_size(window, 750, 650); diff --git a/pubspec.yaml b/pubspec.yaml index ad5f4e2..32ac300 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -3,7 +3,7 @@ description: The state-of-the-art clipboard manager. publish_to: 'none' # Remove this line if you wish to publish to pub.dev -version: 1.0.0+4 +version: 1.0.0+5 environment: sdk: '>=3.1.4 <4.0.0'