LibUnique Example

The example below shows how to correctly set up a UniqueApp instance, send commands and reply to them with the correct response ids.

#include <gtk/gtk.h>
#include <unique/unique.h>

enum
{
  COMMAND_0, /* unused: 0 is an invalid command */

  COMMAND_FOO,
  COMMAND_BAR
};

static GtkWidget *main_window = NULL;

static UniqueResponse
message_received_cb (UniqueApp         *app,
                     UniqueCommand      command,
                     UniqueMessageData *message,
                     guint              time_,
                     gpointer           user_data)
{
  UniqueResponse res;

  switch (command)
    {
    case UNIQUE_ACTIVATE:
      /* move the main window to the screen that sent us the command */
      gtk_window_set_screen (GTK_WINDOW (main_window), unique_message_data_get_screen (message));
      gtk_window_present_with_time (GTK_WINDOW (main_window), time_);
      res = UNIQUE_RESPONSE_OK;
      break;
    case COMMAND_FOO:
      /* "foo" is a command that can fail */
      if (do_command_foo ())
        res = UNIQUE_RESPONSE_OK;
      else
        res = UNIQUE_RESPONSE_FAIL;
      break;
    case COMMAND_BAR:
      /* "bar" is a command that requires user interaction */
      if (!ask_user_for_bar ())
        res = UNIQUE_RESPONSE_CANCEL;
      else
        {
          do_command_bar ();
          res = UNIQUE_RESPONSE_OK;
        }
      break;
    default:
      res = UNIQUE_RESPONSE_OK;
      break;
    }
  
  return res;
}

int
main (int argc, char *argv[])
{
  UniqueApp *app;

  gtk_init (&argc, &argv);

  /* as soon as we create the UniqueApp instance we either have the name
   * we requested ("org.mydomain.MyApplication", in the example) or we
   * don't because there already is an application using the same name
   */
  app = unique_app_new_with_commands ("org.mydomain.MyApplication", NULL,
                                      "foo", COMMAND_FOO,
                                      "bar", COMMAND_BAR,
                                      NULL);

  /* if there already is an instance running, this will return TRUE; there
   * is no race condition because the check is already performed at
   * construction time
   */
  if (unique_app_is_running (app))
    {
      UniqueCommand command;   /* the command we want to send */
      UniqueResponse response; /* the response to our command */

      command = parse_command_line (&argc, &argv);
      if (command == UNIQUE_ACTIVATE)
        response = unique_app_send_message (app, command, NULL);
      else
        {
          UniqueMessageData *message; /* the payload for the command */

          /* here, populate_message() will create the message data using
           * the command line arguments. for instance, if we want to send
           * a list of URIs we can use unique_message_data_set_uris() to
           * correctly populate the UniqueMessageData structure with the
           * URI list.
          message = populate_message (&argc, &argv);

          /* send_message() will block until we get our response back */
          response = unique_app_send_message (app, command, message);

          /* the message is copied, so we need to free it before returning */
          unique_message_data_free (message);
        }

      /* we don't need the application instance anymore */
      g_object_unref (app);

      if (response == UNIQUE_RESPONSE_OK)
        return 0;
      else
        handle_fail_or_user_cancel ();
    }
  else
    {
      /* this is the first instance, so we can proceed with the usual application
       * construction sequence
       */
      main_window = create_main_window ();

      /* the UniqueApp instance must "watch" all the top-level windows the application
       * creates, so that it can terminate the startup notification sequence for us
       */
      unique_app_watch_window (app, GTK_WINDOW (main_window));

      /* using this signal we get notifications from the newly launched instances
       * and we can reply to them; the default signal handler will just return
       * UNIQUE_RESPONSE_OK and terminate the startup notification sequence on each
       * watched window, so you can connect to the message-received signal only if
       * you want to handle the commands and responses
       */
      g_signal_connect (app, "message-received", G_CALLBACK (message_received_cb), NULL);

      gtk_main ();

      /* don't forget to unref the object when cleaning up after the application
       * execution
       */
      g_object_unref (app);
    }

  return 0;
}

Attic/LibUnique/Example (last edited 2013-11-22 16:38:19 by WilliamJonMcCann)