(root)/
glib-2.79.0/
gio/
gfilemonitor.c
       1  /* GIO - GLib Input, Output and Streaming Library
       2   * 
       3   * Copyright (C) 2006-2007 Red Hat, Inc.
       4   *
       5   * SPDX-License-Identifier: LGPL-2.1-or-later
       6   *
       7   * This library is free software; you can redistribute it and/or
       8   * modify it under the terms of the GNU Lesser General Public
       9   * License as published by the Free Software Foundation; either
      10   * version 2.1 of the License, or (at your option) any later version.
      11   *
      12   * This library is distributed in the hope that it will be useful,
      13   * but WITHOUT ANY WARRANTY; without even the implied warranty of
      14   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
      15   * Lesser General Public License for more details.
      16   *
      17   * You should have received a copy of the GNU Lesser General
      18   * Public License along with this library; if not, see <http://www.gnu.org/licenses/>.
      19   *
      20   * Author: Alexander Larsson <alexl@redhat.com>
      21   */
      22  
      23  #include "config.h"
      24  #include <string.h>
      25  
      26  #include "gfilemonitor.h"
      27  #include "gioenumtypes.h"
      28  #include "gmarshal-internal.h"
      29  #include "gfile.h"
      30  #include "gvfs.h"
      31  #include "glibintl.h"
      32  
      33  /**
      34   * GFileMonitor:
      35   *
      36   * Monitors a file or directory for changes.
      37   *
      38   * To obtain a `GFileMonitor` for a file or directory, use
      39   * [method@Gio.File.monitor], [method@Gio.File.monitor_file], or
      40   * [method@Gio.File.monitor_directory].
      41   *
      42   * To get informed about changes to the file or directory you are
      43   * monitoring, connect to the [signal@Gio.FileMonitor::changed] signal. The
      44   * signal will be emitted in the thread-default main context (see
      45   * [method@GLib.MainContext.push_thread_default]) of the thread that the monitor
      46   * was created in (though if the global default main context is blocked, this
      47   * may cause notifications to be blocked even if the thread-default
      48   * context is still running).
      49   **/
      50  
      51  #define DEFAULT_RATE_LIMIT_MSECS 800
      52  
      53  struct _GFileMonitorPrivate
      54  {
      55    gboolean cancelled;
      56  };
      57  
      58  G_DEFINE_ABSTRACT_TYPE_WITH_PRIVATE (GFileMonitor, g_file_monitor, G_TYPE_OBJECT)
      59  
      60  enum
      61  {
      62    PROP_0,
      63    PROP_RATE_LIMIT,
      64    PROP_CANCELLED
      65  };
      66  
      67  static guint g_file_monitor_changed_signal;
      68  
      69  static void
      70  g_file_monitor_set_property (GObject      *object,
      71                               guint         prop_id,
      72                               const GValue *value,
      73                               GParamSpec   *pspec)
      74  {
      75    //GFileMonitor *monitor;
      76  
      77    //monitor = G_FILE_MONITOR (object);
      78  
      79    switch (prop_id)
      80      {
      81      case PROP_RATE_LIMIT:
      82        /* not supported by default */
      83        break;
      84  
      85      default:
      86        G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
      87        break;
      88      }
      89  }
      90  
      91  static void
      92  g_file_monitor_get_property (GObject    *object,
      93                               guint       prop_id,
      94                               GValue     *value,
      95                               GParamSpec *pspec)
      96  {
      97    switch (prop_id)
      98      {
      99      case PROP_RATE_LIMIT:
     100        /* we expect this to be overridden... */
     101        g_value_set_int (value, DEFAULT_RATE_LIMIT_MSECS);
     102        break;
     103  
     104      case PROP_CANCELLED:
     105        //g_mutex_lock (&fms->lock);
     106        g_value_set_boolean (value, FALSE);//fms->cancelled);
     107        //g_mutex_unlock (&fms->lock);
     108        break;
     109  
     110      default:
     111        G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
     112        break;
     113      }
     114  }
     115  
     116  static void
     117  g_file_monitor_dispose (GObject *object)
     118  {
     119    GFileMonitor *monitor = G_FILE_MONITOR (object);
     120  
     121    /* Make sure we cancel on last unref */
     122    g_file_monitor_cancel (monitor);
     123  
     124    G_OBJECT_CLASS (g_file_monitor_parent_class)->dispose (object);
     125  }
     126  
     127  static void
     128  g_file_monitor_init (GFileMonitor *monitor)
     129  {
     130    monitor->priv = g_file_monitor_get_instance_private (monitor);
     131  }
     132  
     133  static void
     134  g_file_monitor_class_init (GFileMonitorClass *klass)
     135  {
     136    GObjectClass *object_class;
     137  
     138    object_class = G_OBJECT_CLASS (klass);
     139    object_class->dispose = g_file_monitor_dispose;
     140    object_class->get_property = g_file_monitor_get_property;
     141    object_class->set_property = g_file_monitor_set_property;
     142  
     143    /**
     144     * GFileMonitor::changed:
     145     * @monitor: a #GFileMonitor.
     146     * @file: a #GFile.
     147     * @other_file: (nullable): a #GFile or #NULL.
     148     * @event_type: a #GFileMonitorEvent.
     149     *
     150     * Emitted when @file has been changed.
     151     *
     152     * If using %G_FILE_MONITOR_WATCH_MOVES on a directory monitor, and
     153     * the information is available (and if supported by the backend),
     154     * @event_type may be %G_FILE_MONITOR_EVENT_RENAMED,
     155     * %G_FILE_MONITOR_EVENT_MOVED_IN or %G_FILE_MONITOR_EVENT_MOVED_OUT.
     156     *
     157     * In all cases @file will be a child of the monitored directory.  For
     158     * renames, @file will be the old name and @other_file is the new
     159     * name.  For "moved in" events, @file is the name of the file that
     160     * appeared and @other_file is the old name that it was moved from (in
     161     * another directory).  For "moved out" events, @file is the name of
     162     * the file that used to be in this directory and @other_file is the
     163     * name of the file at its new location.
     164     *
     165     * It makes sense to treat %G_FILE_MONITOR_EVENT_MOVED_IN as
     166     * equivalent to %G_FILE_MONITOR_EVENT_CREATED and
     167     * %G_FILE_MONITOR_EVENT_MOVED_OUT as equivalent to
     168     * %G_FILE_MONITOR_EVENT_DELETED, with extra information.
     169     * %G_FILE_MONITOR_EVENT_RENAMED is equivalent to a delete/create
     170     * pair.  This is exactly how the events will be reported in the case
     171     * that the %G_FILE_MONITOR_WATCH_MOVES flag is not in use.
     172     *
     173     * If using the deprecated flag %G_FILE_MONITOR_SEND_MOVED flag and @event_type is
     174     * %G_FILE_MONITOR_EVENT_MOVED, @file will be set to a #GFile containing the
     175     * old path, and @other_file will be set to a #GFile containing the new path.
     176     *
     177     * In all the other cases, @other_file will be set to #NULL.
     178     **/
     179    g_file_monitor_changed_signal = g_signal_new (I_("changed"),
     180                                                  G_TYPE_FILE_MONITOR,
     181                                                  G_SIGNAL_RUN_LAST,
     182                                                  G_STRUCT_OFFSET (GFileMonitorClass, changed),
     183                                                  NULL, NULL,
     184                                                  _g_cclosure_marshal_VOID__OBJECT_OBJECT_ENUM,
     185                                                  G_TYPE_NONE, 3,
     186                                                  G_TYPE_FILE, G_TYPE_FILE, G_TYPE_FILE_MONITOR_EVENT);
     187    g_signal_set_va_marshaller (g_file_monitor_changed_signal,
     188                                G_TYPE_FROM_CLASS (klass),
     189                                _g_cclosure_marshal_VOID__OBJECT_OBJECT_ENUMv);
     190  
     191    /**
     192     * GFileMonitor:rate-limit:
     193     *
     194     * The limit of the monitor to watch for changes, in milliseconds.
     195     */
     196    g_object_class_install_property (object_class, PROP_RATE_LIMIT,
     197                                     g_param_spec_int ("rate-limit", NULL, NULL,
     198                                                       0, G_MAXINT, DEFAULT_RATE_LIMIT_MSECS, G_PARAM_READWRITE |
     199                                                       G_PARAM_EXPLICIT_NOTIFY | G_PARAM_STATIC_STRINGS));
     200  
     201    /**
     202     * GFileMonitor:cancelled:
     203     *
     204     * Whether the monitor has been cancelled.
     205     */
     206    g_object_class_install_property (object_class, PROP_CANCELLED,
     207                                     g_param_spec_boolean ("cancelled", NULL, NULL,
     208                                                           FALSE, G_PARAM_READABLE | G_PARAM_STATIC_STRINGS));
     209  }
     210  
     211  /**
     212   * g_file_monitor_is_cancelled:
     213   * @monitor: a #GFileMonitor
     214   * 
     215   * Returns whether the monitor is canceled.
     216   *
     217   * Returns: %TRUE if monitor is canceled. %FALSE otherwise.
     218   **/
     219  gboolean
     220  g_file_monitor_is_cancelled (GFileMonitor *monitor)
     221  {
     222    gboolean res;
     223  
     224    g_return_val_if_fail (G_IS_FILE_MONITOR (monitor), FALSE);
     225  
     226    res = monitor->priv->cancelled;
     227  
     228    return res;
     229  }
     230  
     231  /**
     232   * g_file_monitor_cancel:
     233   * @monitor: a #GFileMonitor.
     234   *
     235   * Cancels a file monitor.
     236   *
     237   * Returns: always %TRUE
     238   **/
     239  gboolean
     240  g_file_monitor_cancel (GFileMonitor *monitor)
     241  {
     242    g_return_val_if_fail (G_IS_FILE_MONITOR (monitor), FALSE);
     243  
     244    if (!monitor->priv->cancelled)
     245      {
     246        G_FILE_MONITOR_GET_CLASS (monitor)->cancel (monitor);
     247  
     248        monitor->priv->cancelled = TRUE;
     249        g_object_notify (G_OBJECT (monitor), "cancelled");
     250      }
     251  
     252    return TRUE;
     253  }
     254  
     255  /**
     256   * g_file_monitor_set_rate_limit:
     257   * @monitor: a #GFileMonitor.
     258   * @limit_msecs: a non-negative integer with the limit in milliseconds
     259   *     to poll for changes
     260   *
     261   * Sets the rate limit to which the @monitor will report
     262   * consecutive change events to the same file.
     263   */
     264  void
     265  g_file_monitor_set_rate_limit (GFileMonitor *monitor,
     266                                 gint          limit_msecs)
     267  {
     268    g_object_set (monitor, "rate-limit", limit_msecs, NULL);
     269  }
     270  
     271  /**
     272   * g_file_monitor_emit_event:
     273   * @monitor: a #GFileMonitor.
     274   * @child: a #GFile.
     275   * @other_file: a #GFile.
     276   * @event_type: a set of #GFileMonitorEvent flags.
     277   *
     278   * Emits the #GFileMonitor::changed signal if a change
     279   * has taken place. Should be called from file monitor
     280   * implementations only.
     281   *
     282   * Implementations are responsible to call this method from the
     283   * [thread-default main context][g-main-context-push-thread-default] of the
     284   * thread that the monitor was created in.
     285   **/
     286  void
     287  g_file_monitor_emit_event (GFileMonitor      *monitor,
     288                             GFile             *child,
     289                             GFile             *other_file,
     290                             GFileMonitorEvent  event_type)
     291  {
     292    g_return_if_fail (G_IS_FILE_MONITOR (monitor));
     293    g_return_if_fail (G_IS_FILE (child));
     294    g_return_if_fail (!other_file || G_IS_FILE (other_file));
     295  
     296    if (monitor->priv->cancelled)
     297      return;
     298  
     299    g_signal_emit (monitor, g_file_monitor_changed_signal, 0, child, other_file, event_type);
     300  }