3

I'm making a cross-platform program with GTK+ v2.24 and after a lot of things done, I bumped in a problem. This is what I'm attempting to do:
1) Pressing enter in a GtkEntry, fire an event (done with the "activate" signal);
2) Make a dialog appear with a simple message and no buttons;
3) Make the dialog disappear in a fade-out effect after 1 second.

Note: While the dialog appears and then fades out, the main top level window should continue to work (as I have a video feed running in it).

I've searched all over the internet but to no avail. I was hoping that the geniuses around here could help me out on this one. Thank you!

EDIT: I had already found this question, but it is about GTK# and I cannot convert it to GTK+.

Community
  • 1
  • 1
StinkyCat
  • 1,236
  • 1
  • 17
  • 31
  • The [answer](http://stackoverflow.com/questions/2827639/in-gtk-is-it-possible-to-make-widgets-fade-in-and-out/3185465#3185465) you linked to applies to C, not C#. Have you tried to implement it? – user4815162342 Apr 26 '13 at 19:35
  • well at least is what the tags say. but no, because the info on the answer is not enough for me to figure it out.. – StinkyCat Apr 27 '13 at 18:57
  • I tried to elaborate on the explanation in the answer. Hope it helps, I'm afraid I can't do much more than that. – user4815162342 Apr 27 '13 at 19:16

2 Answers2

2

I will try to elaborate on the linked answer. Some basics:

  • gtk_widget_get_snapshot converts a live widget to a picture containing the widget's contents. This picture is what you will be fading out.

  • Cairo is a graphic API that implements various drawing primitives, including transparency. Cairo is also used for all GTK drawing, so every GTK application depends on cairo already, and cairo is easy to hook into GTK.

The fadeout animation could go in three steps:

  1. Pop up a top-level window with GTK_WINDOW_POPUP, insert the contents inside and spin the main loop so it gets drawn. Use gtk_widget_get_snapshot to get the widget's image and store it aside.

  2. Remove the widget that shows the contents of the dialog and replace it with a custom widget that inherits from GtkDrawingArea and shows the image you set on the side.

  3. Schedule a timeout function that uses cairo to gradually fade out the pixmap one step at a time, each time also marking the drawing area as dirty, so the ever-more-faded pixmap gets redrawn. Return to the main loop and let the animation play out.

After the second has passed, destroy the top-level window.

Community
  • 1
  • 1
user4815162342
  • 141,790
  • 18
  • 296
  • 355
  • Thank you for the answer. I understood most of it. On Monday I'll be able to give it a try. Once I get some conclusions I'll give some feedback. :) – StinkyCat Apr 28 '13 at 15:48
  • well.. I guess I have number 1 done. Now I'm having a tough time getting number 2 done. Because I want the popup effect, I need to draw the snapshot "in the air" (no container, i guess!). I'm searching around the cairo stuff, but without success. Any thoughts? thks – StinkyCat Apr 29 '13 at 12:16
  • @StinkyCat You cannot draw anything "in the air". Either draw over your existing window, or draw in a top-level window without borders (`GTK_WINDOW_POPUP` type). The latter is technically easier, so I proposed that. – user4815162342 Apr 29 '13 at 14:09
  • ok, but doesn't that contradict what you suggested on number 2? – StinkyCat Apr 29 '13 at 14:24
  • ok, so i got it working with popup window and your timeout function idea to decrease the popup's opacity level until it gets to 0. When it does, it destroys the window and the timeout function returns false to stop the timer. What do you think about this approach? – StinkyCat Apr 29 '13 at 15:02
  • #2 simply proposes to remove the existing dialog contents (which you've already taken a snapshot of), and replace it with a drawing area that just displays the snapshot. Then you fade out the picture. I don't see a contradiction. – user4815162342 Apr 29 '13 at 15:08
  • @StinkyCat If it works for you, then great, you don't need cairo at all. I've never gotten the opacity feature to work on some setups. – user4815162342 Apr 29 '13 at 15:09
  • oh, ok! I thought I had to get rid of the pop window itself. that makes sense. But by the way, can you give me an example of where it woudln't work? because this software is to be used in lots of different pcs (mac/win/linux).. So I wanted to be sure of what issues I might be aiming here. thks for the feedback! – StinkyCat Apr 29 '13 at 15:28
  • @StinkyCat It didn't work on Windows, IIRC, but I guess you'll need to try it yourself to be sure. Good luck! – user4815162342 Apr 29 '13 at 18:55
2

Although I'm asnwering my own question (thus not accepting @user4815162342's one), doesn't mean his is wrong, that it didn't work for me nor my answer is better. I just couldn't figure it out due to lack of skills and time (and I got to my result from @user4815162342 advices actually!).
So this is how I did it:
1) Create popup window with GTK_WINDOW_POPUP;
2) Set the popup's position centered, with a different background color and opacity level and size;
3) Create a label and add it to the CONTAINER(popup);
4) Connected the popup to a timeout with gtk_timeout_add(timeInMS, fadeOutCallback, popup);
5) Create the callback like this:

int MyClass::fadeOutCallback(gpointer caller)  
{  
    gtk_window_set_opacity(GTK_WINDOW(caller), gtk_window_get_opacity(GTK_WINDOW(caller)) - 0.03);  //The 0.03 makes the rate at fading out

    if(gtk_window_get_opacity(GTK_WINDOW(caller)) == 0) //When the popup is completly opaque
    {
        gtk_widget_hide(GTK_WIDGET(caller));
        gtk_widget_destroy(GTK_WIDGET(caller));
        return false; //stop the timer
    }
    return true; //Keeps on calling the callback until the timer reaches timeInMS
}

There are probably much better ways of doing what I want, but this works charm, even with the background video feed playing. Hope this can help anyone. (and thank you again for your input @user4815162342!).

StinkyCat
  • 1,236
  • 1
  • 17
  • 31