Tuesday, December 2, 2008

Overlaying windows over GTK Window

While doing my research to build a vncviewer similar to the drop down disconnect box we see in vmplayer, I realised that there are a couple of techniques to do this, namely as follows:
1.) Modifying vncdisplay.c to emmit signals to the program.
2.) Inserting a one pixel high button on top to catch events.

Both methods has its pros and cons. By using method 1, we will be able to see the entire screen. But by using method 1 also, we will be required to modify the source of the original code (the codebase i was using is gtk-vnc-0.3.7).

In order to stear clear from modifying the author's code, the best way round this is to use method 2, which is to insert a single pixel button on top of the vnc viewer so that we can catch events instead of catching signals. The codes are fairly simple. But this is rather tricky to do because what happens when the mouse leaves the button? The button will close immediately. So, there needs to be a sleep event right?

No, GTK doesn't like sleeping.. somehow.. there will be an error, but I managed to overcome this stupid problem (look at the earlier post for details). But actually the best way to do this is to use an alarm signals.

The idea is as follows:

1.) If the cursor is above the single pixel button, show the disconnect button.
2.) Once the cursor leaves, it, create a signal alarm of 2.
3.) In the event of the signal 'rings' after 2 seconds, we hide the disconnect button.

With that said, the codes are:
// create another window above an existing window
popWindow = gtk_window_new(GTK_WINDOW_POPUP);

// show and hide windows in GTK
void showMenu (GtkWidget *vncdisplay, GdkEventMotion *event) {
gtk_widget_show(popWindow);
}
void choseMenu (GtkWidget *vncdisplay, GdkEventMotion *event) {
signal(SIGALRM, catch_alarm);
alarm(2);
}

// alarm function
void catch_alarm() {
gtk_widget_hide(popWindow);
alarm(0);
}

// signals
gtk_signal_connect(GTK_OBJECT(myButton), "enter", GTK_SIGNAL_FUNC(showMenu), window);
gtk_signal_connect(GTK_OBJECT(myButton), "leave", GTK_SIGNAL_FUNC(hideMenu), window);


Getting coordinates of cursor in GTK

The codes are simple, but we need to get the variables out of its static context.

gint x, y;
gdk_window_get_pointer(window->window, &x, &y, 0);
printf("My cords are: x %d and y: %d", x, y);

Viola!

GTK Error When forking

When you get an error such as a "Fatal IO error" when using GTK and forking a child process. you have just ran into a bug with GTK. GTK doesn't like the way the child exits when it is being forked.

To resolve this, make sure that we exit the child using: _exit (-1), instead of the normal exit function.