Re: Win32 WM_NCDESTROY to GDK Window to GTK Widget signal

Inline answers.

On Wed, Sep 19, 2018 at 5:56 PM LRN via gtk-list <gtk-list gnome org> wrote:
On 19.09.2018 19:40, Michel Donais wrote:
> 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.

This got me thinking: why exactly does GTK not handle WM_DESTROY? That is a
message that child windows get before they are destroyed, whereas WM_NCDESTROY
is only sent after everything is supposed to be dead.

Yep, hence the reason why I'm being more evil to the action, by actually deleting the object immediately instead of doing it eventually.

Window destruction is pretty much a backwards chicken-and-egg issue and I do understand why it would be different per platform, as these are time and context-specific operations, changing how it works depending on the platform, but you pretty much want to have a seamless integration depending if you are in X or Win32 or Mac or whatnot. So it's the kind of thing that will give you a sure headache creating a normalized experience, and will probably end up pissing off more people than it is supposed. Delay it and have the wrath of people who need to react immediately to the user interface change, or react later and feel the wrath of people trying to do things synchronously when they should be doing most of it asynchronously. And what about queued operations.

After that i've looked at gdk_x11_window_destroy_notify().
It checks for the GDK window not being destroyed yet, and if it isn't, the
window is destroyed (it warns if this is done for a non-foreign window), then
detaches the GDK window from GDK display, clears its grab, if any, and unrefs it.

The GDK_WINDOW_DESTROYED() (the ->destroyed field) is weird. It is only set to
TRUE by _gdk_window_destroy_hierarchy(), which sets it *after* it calls
impl->destroy() (which results in XDestroyWindow on X11; i.e. normal windows
are supposed to be XDestroyWindow-ed first, which will cause DestroyNotify,
which will be handled in gdk_x11_window_destroy_notify(), and only after that
the ->destroyed field will be set to TRUE, which will allow
GDK_WINDOW_DESTROYED() to evaluate to TRUE). I don't understand why
gdk_x11_window_destroy_notify() doesn't warn about non-foreign windows being
destroyed all the time.

(all of this IMHO - not an GDK X expert) I think the piece of code assumes you are using a GTK window, which asks for deletion on its own first, and then, sends the event to the system. Also, the Gdk system grabs the hierarchical operation first, and proceeds to do it hierarchically on its own from there. To have the system begging to destroy something internally without GDK knowing about it and having called it first would be something quite odd indeed. So by having the foreign window check, you can say "yeah, this is a foreign window, it's not ours, so it's normal it's being destroyed through system first, and then we get the notification", where a non-foreign window would mean someone meddling in Gdk's own business.

At least, this is what is supposed to be seen in GtkMain.c, where the warning tells you this Destroy operation should never happen, as it should've already happened for non-foreign windows.

W32 backend does it differently - it explicitly sets ->destroyed to TRUE before
calling DestroyWindow().

From what I've seen in systems, usually, windows will react to being destroyed instead of telling it will be destroyed. On my internal system, my first crude implementation assumed exactly that: calling an operation should do the operation. I ended up going to the standardized way of doing things in CWnd, where any operation is done through events instead of done through direct calls.

That is especially true with the window destruction, where all operations are done in WM_DESTROY and WM_NCDESTROY, and WM_NOTIFY for child destruction.

I assume the piece of code is put there because Windows can sometimes decide to delay its operations, especially if our child window happens to be owned by another thread. So the queue might not be empty at that point. I can't tell for sure, but the idea of specifically setting ->destroyed at that point would make sense in a weird and odd sense of way, so more operations can know right now we got destroyed and stop even trying.

But it never is set up later on if the system decides to meddle in its Gtk operations. For me, trying to put a Layout inside an existing HWND, those meddlings are consistent alas. Even more thinking I can theoretically have a (please cry) CWnd -> GtkLayout -> CWnd parenting layout. So the child and the parent could decide to meddle. For Gtk, it's business as usual, though as it's getting a GObject (Root) -> GtkWindow (Foreign) -> GtkLayout -> GtkWidget (Foreign). As long as it understands there's Foreign operations that can happen, I'm happy. And first message was because it wasn't reacting accordingly.

What a mess...

It is... But then, if you code for Win32 exclusively, it kinds of make sense. If you code for X exclusively, it's about ok. But if you code for both, it will not react the same. And we need to drink a lot of courage juice to try to do the good thing.

[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]