Re: Win32 WM_NCDESTROY to GDK Window to GTK Widget signal



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



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