mirror of
git://source.winehq.org/git/wine.git
synced 2024-10-31 10:13:56 +00:00
explorer: Watch the desktop folders for changes and update the launcher list accordingly.
This commit is contained in:
parent
e44f0c8f2d
commit
d62e7f7b9b
1 changed files with 133 additions and 0 deletions
|
@ -252,6 +252,36 @@ error:
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void free_launcher( struct launcher *launcher )
|
||||||
|
{
|
||||||
|
DestroyIcon( launcher->icon );
|
||||||
|
HeapFree( GetProcessHeap(), 0, launcher->path );
|
||||||
|
HeapFree( GetProcessHeap(), 0, launcher->title );
|
||||||
|
HeapFree( GetProcessHeap(), 0, launcher );
|
||||||
|
}
|
||||||
|
|
||||||
|
static BOOL remove_launcher( const WCHAR *folder, const WCHAR *filename, int len_filename )
|
||||||
|
{
|
||||||
|
UINT i;
|
||||||
|
WCHAR *path;
|
||||||
|
BOOL ret = FALSE;
|
||||||
|
|
||||||
|
if (!(path = append_path( folder, filename, len_filename ))) return FALSE;
|
||||||
|
for (i = 0; i < nb_launchers; i++)
|
||||||
|
{
|
||||||
|
if (!strcmpiW( launchers[i]->path, path ))
|
||||||
|
{
|
||||||
|
free_launcher( launchers[i] );
|
||||||
|
if (--nb_launchers)
|
||||||
|
memmove( &launchers[i], &launchers[i + 1], sizeof(launchers[i]) * (nb_launchers - i) );
|
||||||
|
ret = TRUE;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
HeapFree( GetProcessHeap(), 0, path );
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
static BOOL get_icon_text_metrics( HWND hwnd, TEXTMETRICW *tm )
|
static BOOL get_icon_text_metrics( HWND hwnd, TEXTMETRICW *tm )
|
||||||
{
|
{
|
||||||
BOOL ret;
|
BOOL ret;
|
||||||
|
@ -268,6 +298,107 @@ static BOOL get_icon_text_metrics( HWND hwnd, TEXTMETRICW *tm )
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static BOOL process_changes( const WCHAR *folder, char *buf )
|
||||||
|
{
|
||||||
|
FILE_NOTIFY_INFORMATION *info = (FILE_NOTIFY_INFORMATION *)buf;
|
||||||
|
BOOL ret = FALSE;
|
||||||
|
|
||||||
|
for (;;)
|
||||||
|
{
|
||||||
|
switch (info->Action)
|
||||||
|
{
|
||||||
|
case FILE_ACTION_ADDED:
|
||||||
|
case FILE_ACTION_RENAMED_NEW_NAME:
|
||||||
|
if (add_launcher( folder, info->FileName, info->FileNameLength / sizeof(WCHAR) ))
|
||||||
|
ret = TRUE;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case FILE_ACTION_REMOVED:
|
||||||
|
case FILE_ACTION_RENAMED_OLD_NAME:
|
||||||
|
if (remove_launcher( folder, info->FileName, info->FileNameLength / sizeof(WCHAR) ))
|
||||||
|
ret = TRUE;
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
WARN( "unexpected action %u\n", info->Action );
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (!info->NextEntryOffset) break;
|
||||||
|
info = (FILE_NOTIFY_INFORMATION *)((char *)info + info->NextEntryOffset);
|
||||||
|
}
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
static DWORD CALLBACK watch_desktop_folders( LPVOID param )
|
||||||
|
{
|
||||||
|
HWND hwnd = param;
|
||||||
|
HRESULT init = CoInitialize( NULL );
|
||||||
|
HANDLE dir0, dir1, events[2];
|
||||||
|
OVERLAPPED ovl0, ovl1;
|
||||||
|
char *buf0 = NULL, *buf1 = NULL;
|
||||||
|
DWORD count, size = 4096, error = ERROR_OUTOFMEMORY;
|
||||||
|
BOOL ret, redraw;
|
||||||
|
|
||||||
|
dir0 = CreateFileW( desktop_folder, FILE_LIST_DIRECTORY|SYNCHRONIZE, FILE_SHARE_READ|FILE_SHARE_WRITE,
|
||||||
|
NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS|FILE_FLAG_OVERLAPPED, NULL );
|
||||||
|
if (dir0 == INVALID_HANDLE_VALUE) return GetLastError();
|
||||||
|
dir1 = CreateFileW( desktop_folder_public, FILE_LIST_DIRECTORY|SYNCHRONIZE, FILE_SHARE_READ|FILE_SHARE_WRITE,
|
||||||
|
NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS|FILE_FLAG_OVERLAPPED, NULL );
|
||||||
|
if (dir1 == INVALID_HANDLE_VALUE)
|
||||||
|
{
|
||||||
|
CloseHandle( dir0 );
|
||||||
|
return GetLastError();
|
||||||
|
}
|
||||||
|
if (!(ovl0.hEvent = events[0] = CreateEventW( NULL, FALSE, FALSE, NULL ))) goto error;
|
||||||
|
if (!(ovl1.hEvent = events[1] = CreateEventW( NULL, FALSE, FALSE, NULL ))) goto error;
|
||||||
|
if (!(buf0 = HeapAlloc( GetProcessHeap(), 0, size ))) goto error;
|
||||||
|
if (!(buf1 = HeapAlloc( GetProcessHeap(), 0, size ))) goto error;
|
||||||
|
|
||||||
|
for (;;)
|
||||||
|
{
|
||||||
|
ret = ReadDirectoryChangesW( dir0, buf0, size, FALSE, FILE_NOTIFY_CHANGE_FILE_NAME, NULL, &ovl0, NULL );
|
||||||
|
if (!ret)
|
||||||
|
{
|
||||||
|
error = GetLastError();
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
|
ret = ReadDirectoryChangesW( dir1, buf1, size, FALSE, FILE_NOTIFY_CHANGE_FILE_NAME, NULL, &ovl1, NULL );
|
||||||
|
if (!ret)
|
||||||
|
{
|
||||||
|
error = GetLastError();
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
|
|
||||||
|
redraw = FALSE;
|
||||||
|
switch ((error = WaitForMultipleObjects( 2, events, FALSE, INFINITE )))
|
||||||
|
{
|
||||||
|
case WAIT_OBJECT_0:
|
||||||
|
if (!GetOverlappedResult( dir0, &ovl0, &count, FALSE ) || !count) break;
|
||||||
|
if (process_changes( desktop_folder, buf0 )) redraw = TRUE;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case WAIT_OBJECT_0 + 1:
|
||||||
|
if (!GetOverlappedResult( dir1, &ovl1, &count, FALSE ) || !count) break;
|
||||||
|
if (process_changes( desktop_folder_public, buf1 )) redraw = TRUE;
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
|
if (redraw) InvalidateRect( hwnd, NULL, TRUE );
|
||||||
|
}
|
||||||
|
|
||||||
|
error:
|
||||||
|
CloseHandle( dir0 );
|
||||||
|
CloseHandle( dir1 );
|
||||||
|
CloseHandle( events[0] );
|
||||||
|
CloseHandle( events[1] );
|
||||||
|
HeapFree( GetProcessHeap(), 0, buf0 );
|
||||||
|
HeapFree( GetProcessHeap(), 0, buf1 );
|
||||||
|
if (SUCCEEDED( init )) CoUninitialize();
|
||||||
|
return error;
|
||||||
|
}
|
||||||
|
|
||||||
static void add_folder( const WCHAR *folder )
|
static void add_folder( const WCHAR *folder )
|
||||||
{
|
{
|
||||||
static const WCHAR lnkW[] = {'\\','*','.','l','n','k',0};
|
static const WCHAR lnkW[] = {'\\','*','.','l','n','k',0};
|
||||||
|
@ -334,6 +465,8 @@ static void initialize_launchers( HWND hwnd )
|
||||||
add_folder( desktop_folder );
|
add_folder( desktop_folder );
|
||||||
add_folder( desktop_folder_public );
|
add_folder( desktop_folder_public );
|
||||||
if (SUCCEEDED( init )) CoUninitialize();
|
if (SUCCEEDED( init )) CoUninitialize();
|
||||||
|
|
||||||
|
CreateThread( NULL, 0, watch_desktop_folders, hwnd, 0, NULL );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue