]>
Commit | Line | Data |
---|---|---|
1 | /////////////////////////////////////////////////////////////////////////////// | |
2 | // Name: src/gtk/nativewin.cpp | |
3 | // Purpose: wxNativeWindow implementation | |
4 | // Author: Vadim Zeitlin | |
5 | // Created: 2008-03-05 | |
6 | // Copyright: (c) 2008 Vadim Zeitlin <vadim@wxwindows.org> | |
7 | // Licence: wxWindows licence | |
8 | /////////////////////////////////////////////////////////////////////////////// | |
9 | ||
10 | // ============================================================================ | |
11 | // declarations | |
12 | // ============================================================================ | |
13 | ||
14 | // ---------------------------------------------------------------------------- | |
15 | // headers | |
16 | // ---------------------------------------------------------------------------- | |
17 | ||
18 | // for compilers that support precompilation, includes "wx.h". | |
19 | #include "wx/wxprec.h" | |
20 | ||
21 | #ifdef __BORLANDC__ | |
22 | #pragma hdrstop | |
23 | #endif | |
24 | ||
25 | #ifndef WX_PRECOMP | |
26 | #endif // WX_PRECOMP | |
27 | ||
28 | #include "wx/nativewin.h" | |
29 | ||
30 | #include <gtk/gtk.h> | |
31 | #include "wx/gtk/private/gtk2-compat.h" | |
32 | ||
33 | #ifdef GDK_WINDOWING_X11 | |
34 | #include <gdk/gdkx.h> | |
35 | #endif | |
36 | ||
37 | // ============================================================================ | |
38 | // implementation | |
39 | // ============================================================================ | |
40 | ||
41 | // TODO: we probably need equivalent code for other GDK platforms | |
42 | #ifdef GDK_WINDOWING_X11 | |
43 | ||
44 | extern "C" GdkFilterReturn | |
45 | wxNativeContainerWindowFilter(GdkXEvent *gdkxevent, | |
46 | GdkEvent *event, | |
47 | gpointer data) | |
48 | { | |
49 | XEvent * const xevent = static_cast<XEvent *>(gdkxevent); | |
50 | if ( xevent->type == DestroyNotify ) | |
51 | { | |
52 | // we won't need it any more | |
53 | gdk_window_remove_filter(event->any.window, | |
54 | wxNativeContainerWindowFilter, data); | |
55 | ||
56 | // the underlying window got destroyed, notify the C++ object | |
57 | static_cast<wxNativeContainerWindow *>(data)->OnNativeDestroyed(); | |
58 | } | |
59 | ||
60 | return GDK_FILTER_CONTINUE; | |
61 | } | |
62 | ||
63 | #endif // GDK_WINDOWING_X11 | |
64 | ||
65 | bool wxNativeContainerWindow::Create(wxNativeContainerWindowHandle win) | |
66 | { | |
67 | wxCHECK( win, false ); | |
68 | ||
69 | if ( !wxTopLevelWindow::Create(NULL, wxID_ANY, "") ) | |
70 | return false; | |
71 | ||
72 | // we need to realize the window first before reparenting it | |
73 | gtk_widget_realize(m_widget); | |
74 | gdk_window_reparent(gtk_widget_get_window(m_widget), win, 0, 0); | |
75 | ||
76 | #ifdef GDK_WINDOWING_X11 | |
77 | // if the native window is destroyed, our own window will be destroyed too | |
78 | // but GTK doesn't expect it and will complain about "unexpectedly | |
79 | // destroyed" GdkWindow, so intercept to DestroyNotify ourselves to fix | |
80 | // this and also destroy the associated C++ object when its window is | |
81 | // destroyed | |
82 | gdk_window_add_filter(gtk_widget_get_window(m_widget), wxNativeContainerWindowFilter, this); | |
83 | #endif // GDK_WINDOWING_X11 | |
84 | ||
85 | // we should be initially visible as we suppose that the native window we | |
86 | // wrap is (we could use gdk_window_is_visible() to test for this but this | |
87 | // doesn't make much sense unless we also react to visibility changes, so | |
88 | // just suppose it's always shown for now) | |
89 | Show(); | |
90 | ||
91 | return true; | |
92 | } | |
93 | ||
94 | bool wxNativeContainerWindow::Create(wxNativeContainerWindowId anid) | |
95 | { | |
96 | bool rc; | |
97 | #ifdef __WXGTK3__ | |
98 | #ifdef GDK_WINDOWING_X11 | |
99 | GdkWindow * const win = gdk_x11_window_foreign_new_for_display(gdk_display_get_default(), anid); | |
100 | #else | |
101 | GdkWindow * const win = NULL; | |
102 | #endif | |
103 | #else | |
104 | GdkWindow * const win = gdk_window_foreign_new(anid); | |
105 | #endif | |
106 | if ( win ) | |
107 | { | |
108 | rc = Create(win); | |
109 | g_object_unref(win); | |
110 | } | |
111 | else // invalid native window id | |
112 | { | |
113 | rc = false; | |
114 | } | |
115 | ||
116 | return rc; | |
117 | } | |
118 | ||
119 | void wxNativeContainerWindow::OnNativeDestroyed() | |
120 | { | |
121 | // unfortunately we simply can't do anything else than leak memory here: | |
122 | // we really need to call _gdk_window_destroy(m_widget->win, TRUE) to | |
123 | // indicate that the native window was deleted, but we can't do this | |
124 | // because it's a private GDK function and calling normal | |
125 | // gdk_window_destroy() results in X errors while nulling just the window | |
126 | // pointer and destroying m_widget results in many GTK errors | |
127 | GTKDisconnect(m_widget); | |
128 | m_widget = NULL; | |
129 | ||
130 | // notice that we intentionally don't use Close() nor Delete() here as our | |
131 | // window (and the windows of all of our children) is invalid any more and | |
132 | // any attempts to use it, as may happen with the delayed destruction, will | |
133 | // result in GDK warnings at best and crashes or X errors at worst | |
134 | delete this; | |
135 | } | |
136 | ||
137 | wxNativeContainerWindow::~wxNativeContainerWindow() | |
138 | { | |
139 | // nothing to do here, either we have a valid m_widget and it will be | |
140 | // destroyed as usual (this corresponds to manual destruction of this C++ | |
141 | // object) or we are being deleted because the native window was destroyed | |
142 | // and in this case our m_widget was set to NULL by OnNativeDestroyed() | |
143 | } |