summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authormbkma <[email protected]>2026-04-12 09:00:36 +0200
committermbkma <[email protected]>2026-04-12 09:13:55 +0200
commit5987115b7918e6bd090f178d4ee23d1991eae6b0 (patch)
tree3bdb46b2cb88121acecab8c51630c57f3058ca7c
parent20e4b255abbc74dea503810cc9c948963ed40d2a (diff)
downloadmate-utils-fix-save-location.tar.bz2
mate-utils-fix-save-location.tar.xz
rewrite screenshot find save location logicfix-save-location
-rw-r--r--mate-screenshot/src/mate-screenshot.c232
1 files changed, 120 insertions, 112 deletions
diff --git a/mate-screenshot/src/mate-screenshot.c b/mate-screenshot/src/mate-screenshot.c
index df203a88..7c162ea1 100644
--- a/mate-screenshot/src/mate-screenshot.c
+++ b/mate-screenshot/src/mate-screenshot.c
@@ -75,19 +75,9 @@ typedef enum {
SCREENSHOT_EFFECT_BORDER
} ScreenshotEffectType;
-typedef enum
-{
- TEST_LAST_DIR = 0,
- TEST_DESKTOP = 1,
- TEST_TMP = 2,
-} TestType;
-
typedef struct
{
char *base_uris[3];
- char *retval;
- int iteration;
- TestType type;
GdkWindow *window;
GdkRectangle *rectangle;
} AsyncExistenceJob;
@@ -889,143 +879,163 @@ async_existence_job_free (AsyncExistenceJob *job)
g_slice_free (AsyncExistenceJob, job);
}
-static gboolean
-check_file_done (gpointer user_data)
+static void
+on_check_file_done (GObject *source,
+ GAsyncResult *result,
+ gpointer user_data)
{
- AsyncExistenceJob *job = user_data;
+ AsyncExistenceJob *job = g_task_get_task_data (G_TASK (result));
+ GError *error = NULL;
+ char *uri;
- finish_prepare_screenshot (job->retval, job->window, job->rectangle);
+ (void) source;
+ (void) user_data;
- async_existence_job_free (job);
+ uri = g_task_propagate_pointer (G_TASK (result), &error);
- return FALSE;
+ if (error != NULL)
+ {
+ if (!g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED))
+ g_warning ("Unable to determine screenshot save URI: %s", error->message);
+
+ g_error_free (error);
+ screenshot_release_lock ();
+ return;
+ }
+
+ finish_prepare_screenshot (uri, job->window, job->rectangle);
}
static char *
-build_uri (AsyncExistenceJob *job)
+build_screenshot_filename (int iteration)
{
- char *retval, *file_name;
- char *timestamp;
GDateTime *d;
+ char *timestamp, *file_name;
d = g_date_time_new_now_local ();
timestamp = g_date_time_format (d, "%Y-%m-%d %H-%M-%S");
g_date_time_unref (d);
- if (job->iteration == 0)
- {
- /* translators: this is the name of the file that gets made up
- * with the screenshot if the entire screen is taken */
- file_name = g_strdup_printf (_("Screenshot at %s.png"), timestamp);
- }
+ if (iteration == 0)
+ /* translators: this is the name of the file that gets made up
+ * with the screenshot if the entire screen is taken */
+ file_name = g_strdup_printf (_("Screenshot at %s.png"), timestamp);
else
- {
- /* translators: this is the name of the file that gets
- * made up with the screenshot if the entire screen is
- * taken */
- file_name = g_strdup_printf (_("Screenshot at %s - %d.png"), timestamp, job->iteration);
- }
+ /* translators: this is the name of the file that gets
+ * made up with the screenshot if the entire screen is
+ * taken */
+ file_name = g_strdup_printf (_("Screenshot at %s - %d.png"), timestamp, iteration);
- retval = g_build_filename (job->base_uris[job->type], file_name, NULL);
- g_free (file_name);
g_free (timestamp);
-
- return retval;
+ return file_name;
}
-static gboolean
-try_check_file (GIOSchedulerJob *io_job,
- GCancellable *cancellable,
- gpointer data)
+static void
+try_check_file (GTask *task,
+ gpointer source_object,
+ gpointer task_data,
+ GCancellable *cancellable)
{
- AsyncExistenceJob *job = data;
- GFile *file;
- GFileInfo *info;
- GError *error;
- char *uri;
+ AsyncExistenceJob *job = task_data;
+ guint n_types = G_N_ELEMENTS (job->base_uris);
-retry:
- error = NULL;
- uri = build_uri (job);
- file = g_file_new_for_uri (uri);
+ (void) source_object;
- info = g_file_query_info (file, G_FILE_ATTRIBUTE_STANDARD_TYPE,
- G_FILE_QUERY_INFO_NONE, cancellable, &error);
- if (info != NULL)
+ for (guint t = 0; t < n_types; t++)
{
- /* file already exists, iterate again */
- g_object_unref (info);
- g_object_unref (file);
- g_free (uri);
+ GFile *dir;
+ GFileInfo *dir_info;
+ GError *error = NULL;
+ gboolean writable;
- (job->iteration)++;
+ if (job->base_uris[t] == NULL)
+ continue;
- goto retry;
- }
- else
- {
- /* see the error to check whether the location is not accessible
- * or the file does not exist.
- */
- if (error->code == G_IO_ERROR_NOT_FOUND)
+ if (cancellable != NULL && g_cancellable_is_cancelled (cancellable))
{
- GFile *parent;
+ g_task_return_new_error (task,
+ G_IO_ERROR,
+ G_IO_ERROR_CANCELLED,
+ "Screenshot save URI lookup cancelled");
+ return;
+ }
- /* if the parent directory doesn't exist as well, forget the saved
- * directory and treat this as a generic error.
- */
+ dir = g_file_new_for_uri (job->base_uris[t]);
- parent = g_file_get_parent (file);
+ /* Query the directory itself to verify writability before probing names. */
+ dir_info = g_file_query_info (dir,
+ G_FILE_ATTRIBUTE_ACCESS_CAN_WRITE,
+ G_FILE_QUERY_INFO_NONE,
+ cancellable,
+ &error);
+ if (dir_info == NULL)
+ {
+ g_clear_error (&error);
+ g_object_unref (dir);
+ continue;
+ }
- if (!g_file_query_exists (parent, NULL))
- {
- (job->type)++;
- job->iteration = 0;
+ writable = !g_file_info_has_attribute (dir_info, G_FILE_ATTRIBUTE_ACCESS_CAN_WRITE) ||
+ g_file_info_get_attribute_boolean (dir_info, G_FILE_ATTRIBUTE_ACCESS_CAN_WRITE);
+ g_object_unref (dir_info);
- g_object_unref (file);
- g_object_unref (parent);
- goto retry;
- }
- else
- {
- job->retval = uri;
-
- g_object_unref (parent);
- goto out;
- }
+ if (!writable)
+ {
+ g_object_unref (dir);
+ continue;
}
- else
+
+ for (int iteration = 0; ; iteration++)
{
- /* another kind of error, assume this location is not
- * accessible.
- */
- g_free (uri);
- if (job->type == TEST_TMP)
+ char *file_name;
+ GFile *file;
+ GFileInfo *file_info;
+
+ if (cancellable != NULL && g_cancellable_is_cancelled (cancellable))
{
- job->retval = NULL;
- goto out;
+ g_object_unref (dir);
+ g_task_return_new_error (task,
+ G_IO_ERROR,
+ G_IO_ERROR_CANCELLED,
+ "Screenshot save URI lookup cancelled");
+ return;
}
- else
+
+ file_name = build_screenshot_filename (iteration);
+ file = g_file_get_child (dir, file_name);
+ g_free (file_name);
+
+ file_info = g_file_query_info (file,
+ G_FILE_ATTRIBUTE_STANDARD_TYPE,
+ G_FILE_QUERY_INFO_NONE,
+ cancellable,
+ &error);
+ if (file_info != NULL)
{
- (job->type)++;
- job->iteration = 0;
+ g_object_unref (file_info);
+ g_object_unref (file);
+ continue;
+ }
- g_error_free (error);
+ if (error != NULL && error->code == G_IO_ERROR_NOT_FOUND)
+ {
+ char *uri = g_file_get_uri (file);
+ g_clear_error (&error);
g_object_unref (file);
- goto retry;
+ g_object_unref (dir);
+ g_task_return_pointer (task, uri, g_free);
+ return;
}
+
+ g_clear_error (&error);
+ g_object_unref (file);
+ break;
}
- }
-out:
- g_error_free (error);
- g_object_unref (file);
+ g_object_unref (dir);
+ }
- g_io_scheduler_job_send_to_mainloop_async (io_job,
- check_file_done,
- job,
- NULL);
- return FALSE;
+ g_task_return_pointer (task, NULL, NULL);
}
static GdkWindow *
@@ -1063,8 +1073,6 @@ push_check_file_job (GdkRectangle *rectangle)
/* we'll have to free these two */
job->base_uris[1] = get_desktop_dir ();
job->base_uris[2] = g_strconcat ("file://", g_get_tmp_dir (), NULL);
- job->iteration = 0;
- job->type = TEST_LAST_DIR;
job->window = find_current_window ();
if (rectangle != NULL)
@@ -1085,11 +1093,11 @@ push_check_file_job (GdkRectangle *rectangle)
return;
}
- g_io_scheduler_push_job (try_check_file,
- job,
- NULL,
- 0, NULL);
+ GTask *task = g_task_new (NULL, NULL, on_check_file_done, NULL);
+ g_task_set_task_data (task, job, (GDestroyNotify) async_existence_job_free);
+ g_task_run_in_thread (task, try_check_file);
+ g_object_unref (task);
}
static void