mirror of
https://github.com/libretro/RetroArch
synced 2025-01-30 03:32:46 +00:00
win32: Show progress meter on taskbar for downloads (Windows 7 and up)
This commit is contained in:
parent
3145708106
commit
e62e0c83da
@ -16,6 +16,7 @@
|
||||
- PS3: Enable Cheevos.
|
||||
- PSP: Enable threading support through pthreads.
|
||||
- WINDOWS: Improved Unicode support (for cores/directory creation).
|
||||
- WINDOWS: Show progress meter on taskbar for downloads (Windows 7 and up).
|
||||
- WIIU: Overlay support.
|
||||
- WIIU: Transparency support in menu + overlays.
|
||||
- WIIU: New HID pad support.
|
||||
|
@ -93,6 +93,8 @@ static bool g_quit = false;
|
||||
static int g_pos_x = CW_USEDEFAULT;
|
||||
static int g_pos_y = CW_USEDEFAULT;
|
||||
static void *curD3D = NULL;
|
||||
static bool g_taskbar_is_created = false;
|
||||
static unsigned g_taskbar_message = 0;
|
||||
|
||||
ui_window_win32_t main_window;
|
||||
|
||||
@ -147,6 +149,16 @@ static HMONITOR win32_monitor_last;
|
||||
static HMONITOR win32_monitor_all[MAX_MONITORS];
|
||||
static unsigned win32_monitor_count = 0;
|
||||
|
||||
bool win32_taskbar_is_created(void)
|
||||
{
|
||||
return g_taskbar_is_created;
|
||||
}
|
||||
|
||||
void win32_set_taskbar_created(bool created)
|
||||
{
|
||||
g_taskbar_is_created = created;
|
||||
}
|
||||
|
||||
bool doubleclick_on_titlebar_pressed(void)
|
||||
{
|
||||
return doubleclick_on_titlebar;
|
||||
@ -598,6 +610,11 @@ LRESULT CALLBACK WndProcD3D(HWND hwnd, UINT message,
|
||||
return 0;
|
||||
}
|
||||
|
||||
#if _WIN32_WINNT >= 0x0500 /* 2K */
|
||||
if (g_taskbar_message && message == g_taskbar_message)
|
||||
win32_set_taskbar_created(true);
|
||||
#endif
|
||||
|
||||
if (dinput && dinput_handle_message(dinput,
|
||||
message, wparam, lparam))
|
||||
return 0;
|
||||
@ -646,6 +663,11 @@ LRESULT CALLBACK WndProcGL(HWND hwnd, UINT message,
|
||||
return 0;
|
||||
}
|
||||
|
||||
#if _WIN32_WINNT >= 0x0500 /* 2K */
|
||||
if (g_taskbar_message && message == g_taskbar_message)
|
||||
win32_set_taskbar_created(true);
|
||||
#endif
|
||||
|
||||
#if defined(HAVE_D3D9) || defined(HAVE_D3D8)
|
||||
if (dinput_wgl && dinput_handle_message(dinput_wgl,
|
||||
message, wparam, lparam))
|
||||
@ -739,6 +761,11 @@ LRESULT CALLBACK WndProcGDI(HWND hwnd, UINT message,
|
||||
return 0;
|
||||
}
|
||||
|
||||
#if _WIN32_WINNT >= 0x0500 /* 2K */
|
||||
if (g_taskbar_message && message == g_taskbar_message)
|
||||
win32_set_taskbar_created(true);
|
||||
#endif
|
||||
|
||||
#if defined(HAVE_D3D9) || defined(HAVE_D3D8)
|
||||
if (dinput_gdi && dinput_handle_message(dinput_gdi,
|
||||
message, wparam, lparam))
|
||||
@ -767,6 +794,8 @@ bool win32_window_create(void *data, unsigned style,
|
||||
return false;
|
||||
|
||||
#if defined(_WIN32_WINNT) && _WIN32_WINNT >= 0x0500 /* 2K */
|
||||
g_taskbar_message = RegisterWindowMessage("TaskbarButtonCreated");
|
||||
|
||||
ZeroMemory(¬ification_filter, sizeof(notification_filter) );
|
||||
notification_filter.dbcc_size = sizeof(DEV_BROADCAST_DEVICEINTERFACE);
|
||||
notification_filter.dbcc_devicetype = DBT_DEVTYP_DEVICEINTERFACE;
|
||||
|
@ -123,6 +123,10 @@ void win32_window_reset(void);
|
||||
|
||||
void win32_destroy_window(void);
|
||||
|
||||
bool win32_taskbar_is_created(void);
|
||||
|
||||
void win32_set_taskbar_created(bool created);
|
||||
|
||||
#if defined(HAVE_D3D9) || defined(HAVE_D3D8)
|
||||
LRESULT CALLBACK WndProcD3D(HWND hwnd, UINT message,
|
||||
WPARAM wparam, LPARAM lparam);
|
||||
|
@ -35,10 +35,19 @@ static bool null_set_window_opacity(void *data, unsigned opacity)
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool null_set_window_progress(void *data, int progress, bool finished)
|
||||
{
|
||||
(void)data;
|
||||
(void)progress;
|
||||
(void)finished;
|
||||
return true;
|
||||
}
|
||||
|
||||
const video_display_server_t dispserv_null = {
|
||||
null_display_server_init,
|
||||
null_display_server_destroy,
|
||||
null_set_window_opacity,
|
||||
null_set_window_progress,
|
||||
"null"
|
||||
};
|
||||
|
||||
|
@ -15,28 +15,93 @@
|
||||
* If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
/* VC6 needs objbase included before initguid, but nothing else does */
|
||||
#include <objbase.h>
|
||||
#include <initguid.h>
|
||||
#include <windows.h>
|
||||
#include <ntverp.h>
|
||||
|
||||
#ifndef COBJMACROS
|
||||
#define COBJMACROS
|
||||
#define COBJMACROS_DEFINED
|
||||
#endif
|
||||
/* We really just want shobjidl.h, but there's no way to detect its existance at compile time (especially with mingw). however shlobj happens to include it for us when it's supported, which is easier. */
|
||||
#include <shlobj.h>
|
||||
#ifdef COBJMACROS_DEFINED
|
||||
#undef COBJMACROS
|
||||
#endif
|
||||
|
||||
#include "../video_display_server.h"
|
||||
#include "../common/win32_common.h"
|
||||
#include "../../verbosity.h"
|
||||
|
||||
#ifdef __ITaskbarList3_INTERFACE_DEFINED__
|
||||
#define HAS_TASKBAR_EXT
|
||||
|
||||
static ITaskbarList3 *g_taskbarList = NULL;
|
||||
|
||||
/* MSVC really doesn't want CINTERFACE to be used with shobjidl for some reason, but since we use C++ mode,
|
||||
* we need a workaround... so use the names of the COBJMACROS functions instead. */
|
||||
#ifdef __cplusplus
|
||||
#define ITaskbarList3_Release(x) g_taskbarList->Release()
|
||||
#define ITaskbarList3_SetProgressState(a, b, c) g_taskbarList->SetProgressState(b, c)
|
||||
#define ITaskbarList3_SetProgressValue(a, b, c, d) g_taskbarList->SetProgressValue(b, c, d)
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
typedef struct
|
||||
{
|
||||
unsigned opacity;
|
||||
int progress;
|
||||
} dispserv_win32_t;
|
||||
|
||||
/*
|
||||
NOTE: When an application displays a window, its taskbar button is created
|
||||
by the system. When the button is in place, the taskbar sends a
|
||||
TaskbarButtonCreated message to the window. Its value is computed by
|
||||
calling RegisterWindowMessage(L("TaskbarButtonCreated")). That message must
|
||||
be received by your application before it calls any ITaskbarList3 method.
|
||||
*/
|
||||
|
||||
static void* win32_display_server_init(void)
|
||||
{
|
||||
dispserv_win32_t *dispserv = (dispserv_win32_t*)calloc(1, sizeof(*dispserv));
|
||||
HRESULT hr;
|
||||
|
||||
(void)hr;
|
||||
|
||||
if (!dispserv)
|
||||
return NULL;
|
||||
|
||||
#ifdef HAS_TASKBAR_EXT
|
||||
#ifdef _MSC_VER
|
||||
/* when compiling in C++ mode, GUIDs are references instead of pointers */
|
||||
hr = CoCreateInstance(CLSID_TaskbarList, NULL, CLSCTX_INPROC_SERVER, IID_ITaskbarList3, (void**)&g_taskbarList);
|
||||
#else
|
||||
/* mingw GUIDs are pointers instead of references since we're in C mode */
|
||||
hr = CoCreateInstance(&CLSID_TaskbarList, NULL, CLSCTX_INPROC_SERVER, &IID_ITaskbarList3, (void**)&g_taskbarList);
|
||||
#endif
|
||||
|
||||
if (!SUCCEEDED(hr))
|
||||
{
|
||||
g_taskbarList = false;
|
||||
RARCH_ERR("[dispserv]: CoCreateInstance of ITaskbarList3 failed.\n");
|
||||
}
|
||||
#endif
|
||||
|
||||
return dispserv;
|
||||
}
|
||||
|
||||
static void win32_display_server_destroy(void)
|
||||
{
|
||||
|
||||
#ifdef HAS_TASKBAR_EXT
|
||||
if (g_taskbarList && win32_taskbar_is_created())
|
||||
{
|
||||
ITaskbarList3_Release(g_taskbarList);
|
||||
g_taskbarList = NULL;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
static bool win32_set_window_opacity(void *data, unsigned opacity)
|
||||
@ -54,10 +119,55 @@ static bool win32_set_window_opacity(void *data, unsigned opacity)
|
||||
return false;
|
||||
}
|
||||
|
||||
static bool win32_set_window_progress(void *data, int progress, bool finished)
|
||||
{
|
||||
HWND hwnd = win32_get_window();
|
||||
dispserv_win32_t *serv = (dispserv_win32_t*)data;
|
||||
bool ret = false;
|
||||
|
||||
serv->progress = progress;
|
||||
|
||||
#ifdef HAS_TASKBAR_EXT
|
||||
if (!g_taskbarList || !win32_taskbar_is_created())
|
||||
return false;
|
||||
|
||||
if (progress == -1)
|
||||
{
|
||||
if (ITaskbarList3_SetProgressState(g_taskbarList, hwnd, TBPF_INDETERMINATE) == S_OK)
|
||||
ret = true;
|
||||
|
||||
if (!ret)
|
||||
return false;
|
||||
}
|
||||
else if (finished)
|
||||
{
|
||||
if (ITaskbarList3_SetProgressState(g_taskbarList, hwnd, TBPF_NOPROGRESS) == S_OK)
|
||||
ret = true;
|
||||
|
||||
if (!ret)
|
||||
return false;
|
||||
}
|
||||
else if (progress >= 0)
|
||||
{
|
||||
if (ITaskbarList3_SetProgressState(g_taskbarList, hwnd, TBPF_NORMAL) == S_OK)
|
||||
ret = true;
|
||||
|
||||
if (!ret)
|
||||
return false;
|
||||
|
||||
if (ITaskbarList3_SetProgressValue(g_taskbarList, hwnd, progress, 100) == S_OK)
|
||||
ret = true;
|
||||
}
|
||||
#endif
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
const video_display_server_t dispserv_win32 = {
|
||||
win32_display_server_init,
|
||||
win32_display_server_destroy,
|
||||
win32_set_window_opacity,
|
||||
win32_set_window_progress,
|
||||
"win32"
|
||||
};
|
||||
|
||||
|
@ -62,6 +62,7 @@ const video_display_server_t dispserv_x11 = {
|
||||
x11_display_server_init,
|
||||
x11_display_server_destroy,
|
||||
x11_set_window_opacity,
|
||||
NULL,
|
||||
"x11"
|
||||
};
|
||||
|
||||
|
@ -60,3 +60,8 @@ bool video_display_server_set_window_opacity(unsigned opacity)
|
||||
{
|
||||
return current_display_server->set_window_opacity(current_display_server_data, opacity);
|
||||
}
|
||||
|
||||
bool video_display_server_set_window_progress(int progress, bool finished)
|
||||
{
|
||||
return current_display_server->set_window_progress(current_display_server_data, progress, finished);
|
||||
}
|
||||
|
@ -28,12 +28,14 @@ typedef struct video_display_server
|
||||
void *(*init)(void);
|
||||
void (*destroy)(void);
|
||||
bool (*set_window_opacity)(void *data, unsigned opacity);
|
||||
bool (*set_window_progress)(void *data, int progress, bool finished);
|
||||
const char *ident;
|
||||
} video_display_server_t;
|
||||
|
||||
void* video_display_server_init(void);
|
||||
void video_display_server_destroy(void);
|
||||
bool video_display_server_set_window_opacity(unsigned opacity);
|
||||
bool video_display_server_set_window_progress(int progress, bool finished);
|
||||
|
||||
extern const video_display_server_t dispserv_win32;
|
||||
extern const video_display_server_t dispserv_x11;
|
||||
|
@ -99,9 +99,11 @@ struct retro_task
|
||||
* (after calling the callback) */
|
||||
char *error;
|
||||
|
||||
/* -1 = unmettered, 0-100 progress value */
|
||||
/* -1 = unmetered/indeterminate, 0-100 = current progress percentage */
|
||||
int8_t progress;
|
||||
|
||||
void (*progress_cb)(retro_task_t*);
|
||||
|
||||
/* handler can modify but will be
|
||||
* free()d automatically if non-NULL. */
|
||||
char *title;
|
||||
|
@ -99,6 +99,9 @@ static void task_queue_push_progress(retro_task_t *task)
|
||||
else
|
||||
task_queue_msg_push(task, 1, 60, false, "%s...", task->title);
|
||||
}
|
||||
|
||||
if (task->progress_cb)
|
||||
task->progress_cb(task);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -23,6 +23,7 @@
|
||||
#include <retro_timers.h>
|
||||
|
||||
#include "../verbosity.h"
|
||||
#include "../gfx/video_display_server.h"
|
||||
#include "tasks_internal.h"
|
||||
|
||||
enum http_status_enum
|
||||
@ -234,6 +235,11 @@ static bool task_http_retriever(retro_task_t *task, void *data)
|
||||
return true;
|
||||
}
|
||||
|
||||
static void http_transfer_progress_cb(retro_task_t *task)
|
||||
{
|
||||
video_display_server_set_window_progress(task->progress, task->finished);
|
||||
}
|
||||
|
||||
static void* task_push_http_transfer_generic(
|
||||
struct http_connection_t *conn,
|
||||
const char *url, bool mute, const char *type,
|
||||
@ -285,6 +291,7 @@ static void* task_push_http_transfer_generic(
|
||||
t->state = http;
|
||||
t->mute = mute;
|
||||
t->callback = cb;
|
||||
t->progress_cb = http_transfer_progress_cb;
|
||||
t->user_data = user_data;
|
||||
t->progress = -1;
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user