mirror of
https://gitlab.gnome.org/GNOME/glib.git
synced 2025-01-11 23:16:14 +01:00
Fix GWin32DirectoryMonitor
GWin32DirectoryMonitor was quite broken, but nobody had apparently noticed, or at least not filed any bug. Only now with a bleeding edge GTK+ file chooser does the code get exercised in common programs like gtk-demo or GIMP, apparently. Bug #598899.
This commit is contained in:
parent
8eebc18944
commit
d105f431b0
@ -64,9 +64,29 @@ g_win32_directory_monitor_finalize (GObject *base)
|
|||||||
{
|
{
|
||||||
GWin32DirectoryMonitor *self;
|
GWin32DirectoryMonitor *self;
|
||||||
self = G_WIN32_DIRECTORY_MONITOR (base);
|
self = G_WIN32_DIRECTORY_MONITOR (base);
|
||||||
|
|
||||||
g_free (self->priv->file_notify_buffer);
|
if (self->priv->hDirectory == INVALID_HANDLE_VALUE)
|
||||||
g_free (self->priv);
|
{
|
||||||
|
/* If we don't have a directory handle we can free
|
||||||
|
* self->priv->file_notify_buffer and self->priv here. The
|
||||||
|
* callback won't be called obviously any more (and presumably
|
||||||
|
* never has been called).
|
||||||
|
*/
|
||||||
|
g_free (self->priv->file_notify_buffer);
|
||||||
|
self->priv->file_notify_buffer = NULL;
|
||||||
|
g_free (self->priv);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* If we have a directory handle, the OVERLAPPED struct is
|
||||||
|
* passed once more to the callback as a result of the
|
||||||
|
* CloseHandle() done in the cancel method, so self->priv has to
|
||||||
|
* be kept around. The GWin32DirectoryMonitor object is
|
||||||
|
* disappearing, so can't leave a pointer to it in
|
||||||
|
* self->priv->self.
|
||||||
|
*/
|
||||||
|
self->priv->self = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
if (G_OBJECT_CLASS (g_win32_directory_monitor_parent_class)->finalize)
|
if (G_OBJECT_CLASS (g_win32_directory_monitor_parent_class)->finalize)
|
||||||
(*G_OBJECT_CLASS (g_win32_directory_monitor_parent_class)->finalize) (base);
|
(*G_OBJECT_CLASS (g_win32_directory_monitor_parent_class)->finalize) (base);
|
||||||
@ -78,7 +98,13 @@ g_win32_directory_monitor_cancel (GFileMonitor *base)
|
|||||||
GWin32DirectoryMonitor *self;
|
GWin32DirectoryMonitor *self;
|
||||||
self = G_WIN32_DIRECTORY_MONITOR (base);
|
self = G_WIN32_DIRECTORY_MONITOR (base);
|
||||||
|
|
||||||
/* This triggers a last callback() with nBytes=0 */
|
/* This triggers a last callback() with nBytes==0. */
|
||||||
|
|
||||||
|
/* Actually I am not so sure about that, it seems to trigger a last
|
||||||
|
* callback allright, but the way to recognize that it is the final
|
||||||
|
* one is not to check for nBytes==0, I think that was a
|
||||||
|
* misunderstanding.
|
||||||
|
*/
|
||||||
if (self->priv->hDirectory != INVALID_HANDLE_VALUE)
|
if (self->priv->hDirectory != INVALID_HANDLE_VALUE)
|
||||||
CloseHandle (self->priv->hDirectory);
|
CloseHandle (self->priv->hDirectory);
|
||||||
|
|
||||||
@ -94,7 +120,7 @@ g_win32_directory_monitor_callback (DWORD error,
|
|||||||
{
|
{
|
||||||
gulong offset;
|
gulong offset;
|
||||||
PFILE_NOTIFY_INFORMATION pfile_notify_walker;
|
PFILE_NOTIFY_INFORMATION pfile_notify_walker;
|
||||||
gulong file_name_len;
|
glong file_name_len;
|
||||||
gchar *file_name;
|
gchar *file_name;
|
||||||
gchar *path;
|
gchar *path;
|
||||||
GFile *file;
|
GFile *file;
|
||||||
@ -110,23 +136,30 @@ g_win32_directory_monitor_callback (DWORD error,
|
|||||||
G_FILE_MONITOR_EVENT_CREATED, /* FILE_ACTION_RENAMED_NEW_NAME */
|
G_FILE_MONITOR_EVENT_CREATED, /* FILE_ACTION_RENAMED_NEW_NAME */
|
||||||
};
|
};
|
||||||
|
|
||||||
if (!nBytes) /* Monitor was cancelled/finalized */
|
/* If priv->self is NULL the GWin32DirectoryMonitor object has been destroyed. */
|
||||||
return;
|
if (priv->self == NULL ||
|
||||||
|
g_file_monitor_is_cancelled (priv->self) ||
|
||||||
if (g_file_monitor_is_cancelled (G_FILE_MONITOR (priv->self)))
|
priv->file_notify_buffer == NULL)
|
||||||
return; /* and ReadDirectoryChangesW doesn't get called this time */
|
{
|
||||||
|
g_free (priv->file_notify_buffer);
|
||||||
|
g_free (priv);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
offset = 0;
|
offset = 0;
|
||||||
do {
|
do {
|
||||||
pfile_notify_walker = (PFILE_NOTIFY_INFORMATION)(priv->file_notify_buffer + offset);
|
pfile_notify_walker = (PFILE_NOTIFY_INFORMATION)(priv->file_notify_buffer + offset);
|
||||||
|
if (pfile_notify_walker->Action > 0)
|
||||||
|
{
|
||||||
|
file_name = g_utf16_to_utf8 (pfile_notify_walker->FileName, pfile_notify_walker->FileNameLength / sizeof(WCHAR), NULL, &file_name_len, NULL);
|
||||||
|
path = g_build_filename(G_LOCAL_DIRECTORY_MONITOR (priv->self)->dirname, file_name, NULL);
|
||||||
|
file = g_file_new_for_path (path);
|
||||||
|
g_file_monitor_emit_event (priv->self, file, NULL, events [pfile_notify_walker->Action]);
|
||||||
|
g_object_unref (file);
|
||||||
|
g_free (path);
|
||||||
|
g_free (file_name);
|
||||||
|
}
|
||||||
offset += pfile_notify_walker->NextEntryOffset;
|
offset += pfile_notify_walker->NextEntryOffset;
|
||||||
file_name = g_utf16_to_utf8 (pfile_notify_walker->FileName, pfile_notify_walker->FileNameLength / sizeof(WCHAR), NULL, &file_name_len, NULL);
|
|
||||||
path = g_build_filename(G_LOCAL_DIRECTORY_MONITOR (priv->self)->dirname, file_name, NULL);
|
|
||||||
file = g_file_new_for_path (path);
|
|
||||||
g_file_monitor_emit_event (priv->self, file, NULL, events [pfile_notify_walker->Action]);
|
|
||||||
g_object_unref (file);
|
|
||||||
g_free (path);
|
|
||||||
g_free (file_name);
|
|
||||||
} while (pfile_notify_walker->NextEntryOffset);
|
} while (pfile_notify_walker->NextEntryOffset);
|
||||||
|
|
||||||
ReadDirectoryChangesW (priv->hDirectory,
|
ReadDirectoryChangesW (priv->hDirectory,
|
||||||
|
Loading…
Reference in New Issue
Block a user