# HG changeset patch # User bsmith@81767d24-ef19-dc11-ae90-00e081727c95 # Date 1589421147 0 # Node ID 2c2530f8cbefef7259ed63e9d1f7640f5cb18686 # Parent 2dacac5e4023819c639432ddec1b53158f223897 Initial design for system notification support on GTK. Windows, Mac and possibly OS/2 Support will follow. GTK support requires Glib 2.40 or higher. diff -r 2dacac5e4023 -r 2c2530f8cbef dw.h --- a/dw.h Mon Apr 27 08:55:40 2020 +0000 +++ b/dw.h Thu May 14 01:52:27 2020 +0000 @@ -1827,6 +1827,8 @@ HPRINT API dw_print_new(const char *jobname, unsigned long flags, unsigned int pages, void *drawfunc, void *drawdata); int API dw_print_run(HPRINT print, unsigned long flags); void API dw_print_cancel(HPRINT print); +HWND API dw_notification_new(const char *title, HPIXMAP pixmap, const char *description, ...); +int API dw_notification_send(HWND notification); wchar_t * API dw_utf8_to_wchar(const char *utf8string); char * API dw_wchar_to_utf8(const wchar_t *wstring); /* Exported for language bindings */ diff -r 2dacac5e4023 -r 2c2530f8cbef dwtest.c --- a/dwtest.c Mon Apr 27 08:55:40 2020 +0000 +++ b/dwtest.c Thu May 14 01:52:27 2020 +0000 @@ -592,6 +592,8 @@ tmp = dw_file_browse("Pick a file", "dwtest.c", "c", DW_FILE_OPEN ); if ( tmp ) { + HWND notification = dw_notification_new("New file loaded", NULL, "dwtest loaded \"%s\" into the file browser on the Render tab, with \"File Display\" selected from the drop down list.", tmp); + if ( current_file ) { dw_free( current_file ); @@ -601,6 +603,7 @@ read_file(); current_col = current_row = 0; update_render(); + dw_notification_send(notification); } dw_window_set_focus(copypastefield); return 0; diff -r 2dacac5e4023 -r 2c2530f8cbef gtk/dw.c --- a/gtk/dw.c Mon Apr 27 08:55:40 2020 +0000 +++ b/gtk/dw.c Thu May 14 01:52:27 2020 +0000 @@ -119,6 +119,9 @@ GdkPixmap *_dw_tmppixmap = NULL; GdkBitmap *_dw_tmpbitmap = NULL; +#if GLIB_CHECK_VERSION(2,28,0) +GApplication *_DWApp = NULL; +#endif char *_DWDefaultFont = NULL; static char _dw_share_path[PATH_MAX+1] = { 0 }; @@ -1976,6 +1979,8 @@ } #endif +#define DW_APP_DOMAIN_DEFAULT "org.dbsoft.dwindows" + /* * Initializes the Dynamic Windows engine. * Parameters: @@ -1990,6 +1995,12 @@ "1 1 1 1", " c None", " "}; +#if GLIB_CHECK_VERSION(2,28,0) + char appid[101] = {0}; + + /* Generate an Application ID based on the PID initially. */ + snprintf(appid, 100, "%s.pid.%d", DW_APP_DOMAIN_DEFAULT, getpid()); +#endif if(res) { @@ -2024,6 +2035,10 @@ strcpy(_dw_share_path, "/usr/local"); strcat(_dw_share_path, "/share/"); strcat(_dw_share_path, binname); +#if GLIB_CHECK_VERSION(2,28,0) + /* If we have a binary name, use that for the Application ID instead. */ + snprintf(appid, 100, "%s.%s", DW_APP_DOMAIN_DEFAULT, binname); +#endif } if(pathcopy) free(pathcopy); @@ -2094,6 +2109,15 @@ dbgfp = fopen( fname, "w" ); } +#if GLIB_CHECK_VERSION(2,28,0) + /* Initialize the application subsystem on supported versions... + * we generate an application ID based on the binary name or PID + * instead of passing NULL to enable full application support. + */ + _DWApp = g_application_new(appid, G_APPLICATION_FLAGS_NONE); + if(g_application_register(_DWApp, NULL, NULL)) + g_application_activate(_DWApp); +#endif return TRUE; } @@ -12299,6 +12323,75 @@ } /* + * Creates a new system notification if possible. + * Parameters: + * title: The short title of the notification. + * pixmap: Handle to an image to display or NULL if none. + * description: A longer description of the notification, + * or NULL if none is necessary. + * Returns: + * A handle to the notification which can be used to attach a "clicked" event if desired, + * or NULL if it fails or notifications are not supported by the system. + * Remarks: + * This will create a system notification that will show in the notifaction panel + * on supported systems, which may be clicked to perform another task. + */ +HWND dw_notification_new(const char *title, HPIXMAP pixmap, const char *description, ...) +{ +#if GLIB_CHECK_VERSION(2,40,0) + GNotification *notification = g_notification_new(title); + + if(notification) + { + if(description) + { + va_list args; + char outbuf[1025] = {0}; + + va_start(args, description); + vsnprintf(outbuf, 1024, description, args); + va_end(args); + + g_notification_set_body(notification, outbuf); + } +#if GTK_MAJOR_VERSION > 1 + /* GTK 1.x is not implemented as pixbuf, so only allow icons on 2.x */ + if(pixmap && pixmap->pixbuf) + g_notification_set_icon(notification, G_ICON(pixmap->pixbuf)); +#endif + } + return (HWND)notification; +#else + return NULL; +#endif +} + +/* + * Sends a notification created by dw_notification_new() after attaching signal handler. + * Parameters: + * notification: The handle to the notification returned by dw_notification_new(). + * Returns: + * DW_ERROR_NONE on success, DW_ERROR_UNKNOWN on error or not supported. + */ +int dw_notification_send(HWND notification) +{ +#if GLIB_CHECK_VERSION(2,40,0) + if(notification) + { + char id[101] = {0}; + + /* Generate a unique ID based on the notification handle, + * so we can use it to remove the notification in dw_window_destroy(). + */ + snprintf(id, 100, "dw-notification-%llu", (unsigned long long)notification); + g_application_send_notification(_DWApp, id, (GNotification *)notification); + return DW_ERROR_NONE; + } +#endif + return DW_ERROR_UNKNOWN; +} + +/* * Returns some information about the current operating environment. * Parameters: * env: Pointer to a DWEnv struct. diff -r 2dacac5e4023 -r 2c2530f8cbef gtk3/dw.c --- a/gtk3/dw.c Mon Apr 27 08:55:40 2020 +0000 +++ b/gtk3/dw.c Thu May 14 01:52:27 2020 +0000 @@ -3,7 +3,7 @@ * A GTK like cross-platform GUI * GTK3 forwarder module for portabilty. * - * (C) 2000-2019 Brian Smith + * (C) 2000-2020 Brian Smith * (C) 2003-2011 Mark Hessling * (C) 2002 Nickolay V. Shmyrev */ @@ -169,6 +169,9 @@ static void _dw_signal_disconnect(gpointer data, GClosure *closure); GObject *_DWObject = NULL; +#if GLIB_CHECK_VERSION(2,28,0) +GApplication *_DWApp = NULL; +#endif char *_DWDefaultFont = NULL; static char _dw_share_path[PATH_MAX+1] = { 0 }; @@ -1951,6 +1954,8 @@ return NULL; } +#define DW_APP_DOMAIN_DEFAULT "org.dbsoft.dwindows" + /* * Initializes the Dynamic Windows engine. * Parameters: @@ -1959,6 +1964,12 @@ */ int dw_int_init(DWResources *res, int newthread, int *argc, char **argv[]) { +#if GLIB_CHECK_VERSION(2,28,0) + char appid[101] = {0}; + + /* Generate an Application ID based on the PID initially. */ + snprintf(appid, 100, "%s.pid.%d", DW_APP_DOMAIN_DEFAULT, getpid()); +#endif if(res) { _resources.resource_max = res->resource_max; @@ -1992,6 +2003,10 @@ strcpy(_dw_share_path, "/usr/local"); strcat(_dw_share_path, "/share/"); strcat(_dw_share_path, binname); +#if GLIB_CHECK_VERSION(2,28,0) + /* If we have a binary name, use that for the Application ID instead. */ + snprintf(appid, 100, "%s.%s", DW_APP_DOMAIN_DEFAULT, binname); +#endif } if(pathcopy) free(pathcopy); @@ -2021,7 +2036,16 @@ /* Create a global object for glib activities */ _DWObject = g_object_new(G_TYPE_OBJECT, NULL); - + +#if GLIB_CHECK_VERSION(2,28,0) + /* Initialize the application subsystem on supported versions... + * we generate an application ID based on the binary name or PID + * instead of passing NULL to enable full application support. + */ + _DWApp = g_application_new(appid, G_APPLICATION_FLAGS_NONE); + if(g_application_register(_DWApp, NULL, NULL)) + g_application_activate(_DWApp); +#endif return TRUE; } @@ -11002,6 +11026,73 @@ DW_MUTEX_UNLOCK; } + +/* + * Creates a new system notification if possible. + * Parameters: + * title: The short title of the notification. + * pixmap: Handle to an image to display or NULL if none. + * description: A longer description of the notification, + * or NULL if none is necessary. + * Returns: + * A handle to the notification which can be used to attach a "clicked" event if desired, + * or NULL if it fails or notifications are not supported by the system. + * Remarks: + * This will create a system notification that will show in the notifaction panel + * on supported systems, which may be clicked to perform another task. + */ +HWND dw_notification_new(const char *title, HPIXMAP pixmap, const char *description, ...) +{ +#if GLIB_CHECK_VERSION(2,40,0) + GNotification *notification = g_notification_new(title); + + if(notification) + { + if(description) + { + va_list args; + char outbuf[1025] = {0}; + + va_start(args, description); + vsnprintf(outbuf, 1024, description, args); + va_end(args); + + g_notification_set_body(notification, outbuf); + } + if(pixmap && pixmap->pixbuf) + g_notification_set_icon(notification, G_ICON(pixmap->pixbuf)); + } + return (HWND)notification; +#else + return NULL; +#endif +} + +/* + * Sends a notification created by dw_notification_new() after attaching signal handler. + * Parameters: + * notification: The handle to the notification returned by dw_notification_new(). + * Returns: + * DW_ERROR_NONE on success, DW_ERROR_UNKNOWN on error or not supported. + */ +int dw_notification_send(HWND notification) +{ +#if GLIB_CHECK_VERSION(2,40,0) + if(notification) + { + char id[101] = {0}; + + /* Generate a unique ID based on the notification handle, + * so we can use it to remove the notification in dw_window_destroy(). + */ + snprintf(id, 100, "dw-notification-%llu", (unsigned long long)notification); + g_application_send_notification(_DWApp, id, (GNotification *)notification); + return DW_ERROR_NONE; + } +#endif + return DW_ERROR_UNKNOWN; +} + /* * Returns some information about the current operating environment. * Parameters: