changeset 2066:2c2530f8cbef

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.
author bsmith@81767d24-ef19-dc11-ae90-00e081727c95
date Thu, 14 May 2020 01:52:27 +0000
parents 2dacac5e4023
children 3ccd0da07514
files dw.h dwtest.c gtk/dw.c gtk3/dw.c
diffstat 4 files changed, 191 insertions(+), 2 deletions(-) [+]
line wrap: on
line diff
--- 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 */
--- 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;
--- 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.
--- 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 <brian@dbsoft.org>
+ * (C) 2000-2020 Brian Smith <brian@dbsoft.org>
  * (C) 2003-2011 Mark Hessling <mark@rexx.org>
  * (C) 2002 Nickolay V. Shmyrev <shmyrev@yandex.ru>
  */
@@ -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: