1 /*
   2  * Copyright (c) 2004, 2014, Oracle and/or its affiliates. All rights reserved.
   3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   4  *
   5  * This code is free software; you can redistribute it and/or modify it
   6  * under the terms of the GNU General Public License version 2 only, as
   7  * published by the Free Software Foundation.
   8  *
   9  * This code is distributed in the hope that it will be useful, but WITHOUT
  10  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  11  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  12  * version 2 for more details (a copy is included in the LICENSE file that
  13  * accompanied this code).
  14  *
  15  * You should have received a copy of the GNU General Public License version
  16  * 2 along with this work; if not, write to the Free Software Foundation,
  17  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  18  *
  19  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  20  * or visit www.oracle.com if you need additional information or have any
  21  * questions.
  22  */
  23 
  24 /*
  25  * @summary Native window for TaskXEmbedListeners and TaskXEmbedMemory.
  26  */
  27 
  28 #include <gtk/gtk.h>
  29 
  30 #include <string.h>
  31 #include <stdlib.h>
  32 #include <stdio.h>
  33 
  34 int n_children = 0;
  35 
  36 GSList *sockets = NULL;
  37 
  38 GtkWidget *window;
  39 GtkWidget *vbox;
  40 
  41 typedef struct  {
  42     GtkWidget *box;
  43     GtkWidget *frame;
  44     GtkWidget *socket;
  45 } Socket;
  46 
  47 static void quit_cb (gpointer callback_data, guint callback_action, GtkWidget *widget) {
  48     GtkWidget *message_dialog = gtk_message_dialog_new (GTK_WINDOW (window), 0,
  49                                                         GTK_MESSAGE_QUESTION,
  50                                                         GTK_BUTTONS_NONE,
  51                                                         "Really Quit?");
  52     gtk_dialog_add_buttons (GTK_DIALOG (message_dialog),
  53                             GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
  54                             GTK_STOCK_QUIT, GTK_RESPONSE_YES,
  55                             NULL);
  56 
  57     gtk_dialog_set_default_response (GTK_DIALOG (message_dialog), GTK_RESPONSE_YES);
  58 
  59     if (gtk_dialog_run (GTK_DIALOG (message_dialog)) == GTK_RESPONSE_YES)
  60         gtk_widget_destroy (window);
  61 
  62     gtk_widget_destroy (message_dialog);
  63 }
  64 
  65 static void socket_destroyed (GtkWidget *widget, Socket *socket) {
  66     sockets = g_slist_remove (sockets, socket);
  67     g_free (socket);
  68 }
  69 
  70 static void plug_added (GtkWidget *widget, Socket *socket) {
  71     g_print ("Plug added to socket\n");
  72 
  73     gtk_widget_show (socket->socket);
  74     gtk_widget_hide (socket->frame);
  75 }
  76 
  77 static gboolean plug_removed (GtkWidget *widget, Socket *socket) {
  78     g_print ("Plug removed from socket\n");
  79 
  80     gtk_widget_hide (socket->socket);
  81     gtk_widget_show (socket->frame);
  82 
  83     return TRUE;
  84 }
  85 
  86 static Socket * create_socket (void) {
  87     GtkWidget *label;
  88 
  89     Socket *socket = g_new (Socket, 1);
  90 
  91     socket->box = gtk_vbox_new (FALSE, 0);
  92 
  93     socket->socket = gtk_socket_new ();
  94 
  95     gtk_box_pack_start (GTK_BOX (socket->box), socket->socket, TRUE, TRUE, 0);
  96 
  97     socket->frame = gtk_frame_new (NULL);
  98     gtk_frame_set_shadow_type (GTK_FRAME (socket->frame), GTK_SHADOW_IN);
  99     gtk_box_pack_start (GTK_BOX (socket->box), socket->frame, TRUE, TRUE, 0);
 100     gtk_widget_show (socket->frame);
 101 
 102     label = gtk_label_new (NULL);
 103     gtk_label_set_markup (GTK_LABEL (label), "<span color=\"red\">Empty</span>");
 104     gtk_container_add (GTK_CONTAINER (socket->frame), label);
 105     gtk_widget_show (label);
 106 
 107     sockets = g_slist_prepend (sockets, socket);
 108 
 109 
 110     g_signal_connect (G_OBJECT (socket->socket), "destroy",
 111                       G_CALLBACK (socket_destroyed), socket);
 112     g_signal_connect (G_OBJECT (socket->socket), "plug_added",
 113                       G_CALLBACK (plug_added), socket);
 114     g_signal_connect (G_OBJECT (socket->socket), "plug_removed",
 115                       G_CALLBACK (plug_removed), socket);
 116 
 117     return socket;
 118 }
 119 
 120 void remove_child (void) {
 121     if (sockets) {
 122         Socket *socket = sockets->data;
 123         gtk_widget_destroy (socket->box);
 124     }
 125 }
 126 
 127 static gboolean
 128 child_read_watch (GIOChannel *channel, GIOCondition cond, gpointer data)
 129 {
 130     GIOStatus status;
 131     GError *error = NULL;
 132     char *line;
 133     gsize term;
 134     int xid;
 135 
 136     status = g_io_channel_read_line (channel, &line, NULL, &term, &error);
 137     switch (status) {
 138         case G_IO_STATUS_NORMAL:
 139             line[term] = '\0';
 140             xid = strtol (line, NULL, 0);
 141             if (xid == 0) {
 142                 fprintf (stderr, "Invalid window id '%s'\n", line);
 143             } else {
 144                 Socket *socket = create_socket ();
 145                 gtk_box_pack_start (GTK_BOX (vbox), socket->box, TRUE, TRUE, 0);
 146                 gtk_widget_show (socket->box);
 147         
 148                 gtk_socket_add_id (GTK_SOCKET (socket->socket), xid);
 149             }
 150             g_free (line);
 151             return TRUE;
 152         case G_IO_STATUS_AGAIN:
 153             return TRUE;
 154         case G_IO_STATUS_EOF:
 155             n_children--;
 156             g_io_channel_shutdown (channel, FALSE, NULL);
 157             return FALSE;
 158         case G_IO_STATUS_ERROR:
 159             fprintf (stderr, "Error reading fd from child: %s\n", error->message);
 160             exit (1);
 161             return FALSE;
 162         default:
 163             g_assert_not_reached ();
 164             return FALSE;
 165     }
 166 }
 167 
 168 int main (int argc, char *argv[]) {
 169     GtkWidget *hbox;
 170     Socket *socket;
 171     char buffer[20];
 172     FILE *idFile;
 173 
 174     gtk_init (&argc, &argv);
 175 
 176     window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
 177     gtk_widget_set_size_request (window, 300, 300);
 178     gtk_widget_set_uposition (window, 100, 100);
 179     g_signal_connect (window, "destroy",
 180                       G_CALLBACK (gtk_main_quit), NULL);
 181 
 182     gtk_window_set_title (GTK_WINDOW (window), "XEmbed Test");
 183 
 184 
 185     gtk_container_set_border_width (GTK_CONTAINER (window), 0);
 186 
 187     vbox = gtk_vbox_new (FALSE, 0);
 188     hbox = gtk_hbox_new (FALSE, 0);
 189     gtk_container_add (GTK_CONTAINER (window), vbox);
 190 
 191     gtk_box_pack_start (GTK_BOX(vbox), hbox, FALSE, FALSE, 0);
 192 
 193     socket = create_socket ();
 194     gtk_box_pack_start (GTK_BOX (vbox), socket->box, TRUE, TRUE, 0);
 195     sprintf(buffer, "%#lx", (gulong) gtk_socket_get_id (GTK_SOCKET (socket->socket)));
 196     idFile = fopen("window_id", "w");
 197     if (idFile != NULL) {
 198         fprintf(idFile, "%s", buffer);
 199         fclose(idFile);
 200     } else {
 201         exit(1);
 202     }
 203 
 204     gtk_widget_show_all (window);
 205     gtk_main ();
 206 
 207     if (n_children) {
 208         g_print ("Waiting for children to exit\n");
 209         while (n_children)
 210             g_main_context_iteration (NULL, TRUE);
 211     }
 212 
 213     return 0;
 214 }