]>
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 | ||
33 | #ifdef GDK_WINDOWING_X11 | |
34 | #include <X11/Xlib.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(m_widget->window, 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(m_widget->window, 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 | GdkWindow * const win = gdk_window_foreign_new(anid); | |
98 | if ( win ) | |
99 | { | |
100 | rc = Create(win); | |
101 | g_object_unref(win); | |
102 | } | |
103 | else // invalid native window id | |
104 | { | |
105 | rc = false; | |
106 | } | |
107 | ||
108 | return rc; | |
109 | } | |
110 | ||
111 | void wxNativeContainerWindow::OnNativeDestroyed() | |
112 | { | |
113 | // unfortunately we simply can't do anything else than leak memory here: | |
114 | // we really need to call _gdk_window_destroy(m_widget->win, TRUE) to | |
115 | // indicate that the native window was deleted, but we can't do this | |
116 | // because it's a private GDK function and calling normal | |
117 | // gdk_window_destroy() results in X errors while nulling just the window | |
118 | // pointer and destroying m_widget results in many GTK errors | |
119 | m_widget = NULL; | |
120 | ||
121 | // notice that we intentionally don't use Close() nor Delete() here as our | |
122 | // window (and the windows of all of our children) is invalid any more and | |
123 | // any attempts to use it, as may happen with the delayed destruction, will | |
124 | // result in GDK warnings at best and crashes or X errors at worst | |
125 | delete this; | |
126 | } | |
127 | ||
128 | wxNativeContainerWindow::~wxNativeContainerWindow() | |
129 | { | |
130 | // nothing to do here, either we have a valid m_widget and it will be | |
131 | // destroyed as usual (this corresponds to manual destruction of this C++ | |
132 | // object) or we are being deleted because the native window was destroyed | |
133 | // and in this case our m_widget was set to NULL by OnNativeDestroyed() | |
134 | } |