Sorry for the delay, I wanted to make sure I thoroughly test out what's the
best, now that I allowed myself to modify the GTK source.

So, the code actually works using append_event, but it might not be the
best solution, as the WM_NCDESTROY event is terminal, so merely appending
an operation for future consideration is probably not the best case.

I ended up modifying it to do

>   event->any.window = g_object_ref(window);
>    _gdk_event_emit(event);

instead, which emits the destruction immediately, instead of having the
event appended, and eventually reacting to it when the window got
destroyed. In some instances, the gdk_window_destroy_notify is receiving an
already destroyed event at that point, since I added a destroy-event signal
handler on my side that deletes the window, so it's all good. Note: I am
not certain of the g_object_ref(window) addition, if I don't put it, it
seems to destroy the GdkWindow earlier than supposed, and I get a crash
in do_synthesize_crossing_event, but jury's still up for debate on that.

Also, I want to make sure foreign windows are being processed as usual, so

>   return_val = (window->window_type != GDK_WINDOW_FOREIGN);

At that point, I also modified gtkmain.c so it understands we are having
non-GTK windows underneath our GTK window. So I hacked through the
GDK_DESTROY event, which already got in comments it's being forced in
destruction by some evil outside forces to check if its window is the
automatically generated root window of our environment. These might not
have Gtk objects associated with them, so it's fair play to assume they
should take care of themselves, even when there's a parent. Before, if the
operation was done through an append, we could've had the entire hierarchy,
but now, we are getting processed immediately, so it's fair play we are
processing it right now, no matter the kind of window.

>    case GDK_DESTROY:
>      /* Unexpected GDK_DESTROY from the outside, ignore for
>       * child windows, handle like a GDK_DELETE for toplevels
>       */
>      if (!gtk_widget_get_parent (event_widget) ||
(event->any.window->parent && event->any.window->parent->window_type ==
GDK_WINDOW_ROOT))

Thanks for the help. Hopefully I will be able to make my thing work without
hacking off gtk too much, goal is to be as standard as possible. My code
still is buggy as hell, but at least, it seems like this is a great start.


On Tue, Sep 18, 2018 at 12:54 PM LRN via gtk-list <gtk-list@gnome.org>
wrote:

> On 18.09.2018 19:38, Michel Donais wrote:
> > You are right, this is on GTK3. Hopefully, once GTK4 becomes predominant,
> > it might not be useful to have foreign windows. But TBD!
> >
> > The problem is as follows:
> >
> >>      if ((window != NULL) && (msg->hwnd != GetDesktopWindow ()))
> >> gdk_window_destroy_notify (window);
> >
> > This line actually destroys the window, so GDK_WINDOW_DESTROYED becomes
> > true at that point. This is due to:
> >
> >> static void gdk_win32_window_destroy_notify (GdkWindow *window)
> >
> > where
> >
> >> if (!GDK_WINDOW_DESTROYED (window)),
> >
> > it
> >
> >>       _gdk_window_destroy (window, TRUE);
> >
> > So the line after, once the window is actually destroyed, it breaks
> >
> >>      if (window == NULL || GDK_WINDOW_DESTROYED (window))
> >> break;
> >
> > and never enters the following lines.
> >
> >>      event = gdk_event_new (GDK_DESTROY);
> >>      event->any.window = window;
> >>
> >>      _gdk_win32_append_event (event);
> >
>
> I see. I've looked at X11 backend, and it does things a bit differently -
> it
> always queues a GDK_DESTROY event (due to how event processing is being
> done in
> X11 - any notification results in an event, it seems), while also maybe
> calling
> destory_notify() in the process.
>
> If you rewrite WM_NCDESTROY handling to:
>
> if ((pointer_grab != NULL && pointer_grab -> window == window) ||
>     (keyboard_grab && keyboard_grab -> window == window))
>   {
>     GdkDevice *device = gdk_device_manager_get_client_pointer
> (device_manager);
>     gdk_device_ungrab (device, msg -> time);
>   }
>
> if (window != NULL)
>   {
>     event = gdk_event_new (GDK_DESTROY);
>     event->any.window = window;
>
>     _gdk_win32_append_event (event);
>   }
>
> if ((window != NULL) && (msg->hwnd != GetDesktopWindow ()))
>   gdk_window_destroy_notify (window);
>
> return_val = TRUE;
> break;
>
> then what happens in your application?
>
> _______________________________________________
> gtk-list mailing list
> gtk-list@gnome.org
> https://mail.gnome.org/mailman/listinfo/gtk-list
>
_______________________________________________
gtk-list mailing list
gtk-list@gnome.org
https://mail.gnome.org/mailman/listinfo/gtk-list

Reply via email to