#include <stdio.h>
#include <gtk/gtk.h>
#include <gdk/gdkx.h>
#include <gdk/gdkkeysyms.h>
#include <X11/Xlib.h>

const int USE_GRAB = 0;
const int USE_XSETINPUTFOCUS = 0;

GtkWidget *tmpShell = NULL;
gboolean closeShell (GtkWidget *widget, GdkEventKey *event, gpointer user_data) {
	if (tmpShell) {
		gtk_widget_destroy (tmpShell);
		tmpShell = NULL;
	}
}

int state = 0;

static gboolean
popup_grab_on_window (GdkWindow *window,
                      guint32    activate_time)
{
  if ((gdk_pointer_grab (window, TRUE,
                         GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK |
                         GDK_POINTER_MOTION_MASK,
                         NULL, NULL, activate_time) == 0))
    {
      if (gdk_keyboard_grab (window, TRUE,
                             activate_time) == 0)
        return TRUE;
      else
        {
          gdk_display_pointer_ungrab (gdk_drawable_get_display (window),
                                      activate_time);
          return FALSE;
        }
    }

  return FALSE;
}


gboolean key_down (GtkWidget *widget, GdkEventKey *event, gpointer user_data) {
	printf ("key_down %i (state %d)\n", widget, state);
	if (state == 0) {
		printf ("*** Create override_redirect window\n");
		GtkWidget *text;
		tmpShell  = gtk_window_new (GTK_WINDOW_POPUP);
		//tmpShell  = gtk_window_new (GTK_WINDOW_TOPLEVEL);	
		gtk_window_set_default_size (GTK_WINDOW (tmpShell), 140, 125);
		g_signal_connect (G_OBJECT (tmpShell), "key-press-event", G_CALLBACK (key_down), NULL);			
		text = gtk_entry_new ();
		gtk_container_add (GTK_CONTAINER (tmpShell), text);
		gtk_widget_show_all (tmpShell);		
		state = 1;
	} else if (state == 1) {
		printf ("*** Give the window focus\n");

		if( USE_GRAB ) {
			printf ("+++ Grab pointer and keyboard focus\n");
 			gdk_pointer_grab (tmpShell->window, TRUE,
				GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK | GDK_POINTER_MOTION_MASK,
				NULL, NULL, gtk_get_current_event_time ());
			gdk_keyboard_grab (tmpShell->window, TRUE, gtk_get_current_event_time ());
		}

		if( USE_XSETINPUTFOCUS ) {
			Display *dpy;
			XID id;
			printf ("+++ Use XSetInputFocus to give focus\n");
			dpy = gdk_x11_drawable_get_xdisplay (tmpShell->window);
			id = gdk_x11_drawable_get_xid (tmpShell->window);
			XSetInputFocus(dpy, id, RevertToParent, CurrentTime);
		} else {
			printf ("+++ Use gtk_widget_grab_focus to give focus\n");
			gtk_widget_grab_focus (tmpShell);
		}
		state = 2;
 	} else {
		printf ("*** Destroy the window\n");
		gtk_widget_destroy (tmpShell);
		tmpShell = NULL;
		state = 0;
	}
	return 0;
}

gboolean focus_out (GtkWidget *widget, GdkEventFocus *event, gpointer user_data) {
	printf ("focus out %i\n", widget);
	return 0;
}

gboolean focus_in (GtkWidget *widget, GdkEventFocus *event, gpointer user_data) {
	printf ("focus in %i\n", widget);
	return 0;
}

int main (int argc, char** argv) {
	GtkWidget *shellHandle;
	GtkWidget *text;
	gtk_init_check (&argc, &argv);
	shellHandle = gtk_window_new (GTK_WINDOW_TOPLEVEL);	
	g_signal_connect (G_OBJECT (shellHandle), "key-press-event", G_CALLBACK (key_down), NULL);	
	g_signal_connect (G_OBJECT (shellHandle), "focus-out-event", G_CALLBACK (focus_out), NULL);	
	g_signal_connect (G_OBJECT (shellHandle), "focus-in-event", G_CALLBACK (focus_in), NULL);	
	g_signal_connect (G_OBJECT (shellHandle), "destroy", G_CALLBACK (gtk_main_quit), NULL);
	g_signal_connect (G_OBJECT (shellHandle), "delete_event",G_CALLBACK (gtk_main_quit), NULL);
	gtk_window_set_default_size (GTK_WINDOW (shellHandle), 280, 250);
	text = gtk_entry_new ();
	gtk_container_add (GTK_CONTAINER (shellHandle), text);
	gtk_widget_show_all (shellHandle);
	gtk_main();
}
