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