]> git.saurik.com Git - wxWidgets.git/blob - src/gtk/minifram.cpp
Fox around a bug in GTK's GtkNotebook
[wxWidgets.git] / src / gtk / minifram.cpp
1 /////////////////////////////////////////////////////////////////////////////
2 // Name: minifram.cpp
3 // Purpose:
4 // Author: Robert Roebling
5 // Id: $Id$
6 // Copyright: (c) 1998 Robert Roebling
7 // Licence: wxWindows licence
8 /////////////////////////////////////////////////////////////////////////////
9
10 #ifdef __GNUG__
11 #pragma implementation "minifram.h"
12 #endif
13
14 #include "wx/minifram.h"
15 #include "wx/dcscreen.h"
16
17 #include "gtk/gtk.h"
18 #include "wx/gtk/win_gtk.h"
19
20 #include "gdk/gdk.h"
21 #include "gdk/gdkprivate.h"
22 #include "gdk/gdkx.h"
23
24 //-----------------------------------------------------------------------------
25 // idle system
26 //-----------------------------------------------------------------------------
27
28 extern void wxapp_install_idle_handler();
29 extern bool g_isIdle;
30
31 //-----------------------------------------------------------------------------
32 // data
33 //-----------------------------------------------------------------------------
34
35 extern bool g_blockEventsOnDrag;
36 extern bool g_blockEventsOnScroll;
37
38 //-----------------------------------------------------------------------------
39 // local functions
40 //-----------------------------------------------------------------------------
41
42 /* draw XOR rectangle when moving mine frame around */
43
44 static void DrawFrame( GtkWidget *widget, int x, int y, int w, int h )
45 {
46 int org_x = 0;
47 int org_y = 0;
48 gdk_window_get_origin( widget->window, &org_x, &org_y );
49 x += org_x;
50 y += org_y;
51
52 GdkGC *gc = gdk_gc_new( GDK_ROOT_PARENT() );
53 gdk_gc_set_subwindow( gc, GDK_INCLUDE_INFERIORS );
54 gdk_gc_set_function( gc, GDK_INVERT );
55
56 gdk_draw_rectangle( GDK_ROOT_PARENT(), gc, FALSE, x, y, w, h );
57 gdk_gc_unref( gc );
58 }
59
60 //-----------------------------------------------------------------------------
61 // "expose_event" of m_mainWidget
62 //-----------------------------------------------------------------------------
63
64 static void gtk_window_own_expose_callback( GtkWidget *widget, GdkEventExpose *gdk_event, wxFrame *win )
65 {
66 if (g_isIdle) wxapp_install_idle_handler();
67
68 if (!win->HasVMT()) return;
69 if (gdk_event->count > 0) return;
70
71 gtk_draw_shadow( widget->style,
72 widget->window,
73 GTK_STATE_NORMAL,
74 GTK_SHADOW_OUT,
75 0, 0,
76 win->m_width, win->m_height );
77
78 if (!win->m_title.IsEmpty() &&
79 ((win->m_windowStyle & wxCAPTION) ||
80 (win->m_windowStyle & wxTINY_CAPTION_HORIZ) ||
81 (win->m_windowStyle & wxTINY_CAPTION_VERT)))
82 {
83 GdkGC *gc = gdk_gc_new( widget->window );
84 GdkFont *font = wxSMALL_FONT->GetInternalFont(1.0);
85 int x = 2;
86 if (win->m_windowStyle & wxSYSTEM_MENU) x = 18;
87
88 gdk_gc_set_foreground( gc, &widget->style->bg[GTK_STATE_SELECTED] );
89 gdk_draw_rectangle( widget->window, gc, TRUE,
90 x,
91 3,
92 win->m_width - 4 - x,
93 font->ascent + font->descent+1 );
94
95 gdk_gc_set_foreground( gc, &widget->style->white );
96 gdk_draw_string( widget->window, font, gc,
97 x+2,
98 3+font->ascent,
99 win->m_title.mb_str() );
100
101 gdk_gc_unref( gc );
102 }
103 }
104
105 //-----------------------------------------------------------------------------
106 // "draw" of m_mainWidget
107 //-----------------------------------------------------------------------------
108
109 static void gtk_window_own_draw_callback( GtkWidget *widget, GdkRectangle *WXUNUSED(rect), wxFrame *win )
110 {
111 if (g_isIdle) wxapp_install_idle_handler();
112
113 if (!win->HasVMT()) return;
114
115 gtk_draw_shadow( widget->style,
116 widget->window,
117 GTK_STATE_NORMAL,
118 GTK_SHADOW_OUT,
119 0, 0,
120 win->m_width, win->m_height );
121
122 if (!win->m_title.IsEmpty() &&
123 ((win->m_windowStyle & wxCAPTION) ||
124 (win->m_windowStyle & wxTINY_CAPTION_HORIZ) ||
125 (win->m_windowStyle & wxTINY_CAPTION_VERT)))
126 {
127 GdkGC *gc = gdk_gc_new( widget->window );
128 GdkFont *font = wxSMALL_FONT->GetInternalFont(1.0);
129 int x = 2;
130 if (win->m_windowStyle & wxSYSTEM_MENU) x = 17;
131
132 gdk_gc_set_foreground( gc, &widget->style->bg[GTK_STATE_SELECTED] );
133 gdk_draw_rectangle( widget->window, gc, TRUE,
134 x,
135 3,
136 win->m_width - 4 - x,
137 font->ascent + font->descent+1 );
138
139 gdk_gc_set_foreground( gc, &widget->style->white );
140 gdk_draw_string( widget->window, font, gc,
141 x+2,
142 3+font->ascent,
143 win->m_title.mb_str() );
144
145 gdk_gc_unref( gc );
146 }
147 }
148
149 //-----------------------------------------------------------------------------
150 // "button_press_event" of m_mainWidget
151 //-----------------------------------------------------------------------------
152
153 static gint gtk_window_button_press_callback( GtkWidget *widget, GdkEventButton *gdk_event, wxMiniFrame *win )
154 {
155 if (g_isIdle) wxapp_install_idle_handler();
156
157 if (!win->HasVMT()) return FALSE;
158 if (g_blockEventsOnDrag) return TRUE;
159 if (g_blockEventsOnScroll) return TRUE;
160
161 if (win->m_isDragging) return TRUE;
162
163 gdk_pointer_grab( widget->window, FALSE,
164 (GdkEventMask)
165 (GDK_BUTTON_PRESS_MASK |
166 GDK_BUTTON_RELEASE_MASK |
167 GDK_POINTER_MOTION_MASK |
168 GDK_POINTER_MOTION_HINT_MASK |
169 GDK_BUTTON_MOTION_MASK |
170 GDK_BUTTON1_MOTION_MASK),
171 (GdkWindow *) NULL,
172 (GdkCursor *) NULL,
173 GDK_CURRENT_TIME );
174
175 win->m_diffX = (int)gdk_event->x;
176 win->m_diffY = (int)gdk_event->y;
177 DrawFrame( widget, 0, 0, win->m_width, win->m_height );
178 win->m_oldX = 0;
179 win->m_oldY = 0;
180
181 win->m_isDragging = TRUE;
182
183 return TRUE;
184 }
185
186 //-----------------------------------------------------------------------------
187 // "button_release_event" of m_mainWidget
188 //-----------------------------------------------------------------------------
189
190 static gint gtk_window_button_release_callback( GtkWidget *widget, GdkEventButton *gdk_event, wxMiniFrame *win )
191 {
192 if (g_isIdle) wxapp_install_idle_handler();
193
194 if (!win->HasVMT()) return FALSE;
195 if (g_blockEventsOnDrag) return TRUE;
196 if (g_blockEventsOnScroll) return TRUE;
197
198 if (!win->m_isDragging) return TRUE;
199
200 win->m_isDragging = FALSE;
201
202 int x = (int)gdk_event->x;
203 int y = (int)gdk_event->y;
204
205 DrawFrame( widget, win->m_oldX, win->m_oldY, win->m_width, win->m_height );
206 gdk_pointer_ungrab ( GDK_CURRENT_TIME );
207 int org_x = 0;
208 int org_y = 0;
209 gdk_window_get_origin( widget->window, &org_x, &org_y );
210 x += org_x - win->m_diffX;
211 y += org_y - win->m_diffY;
212 win->m_x = x;
213 win->m_y = y;
214 gtk_widget_set_uposition( win->m_widget, x, y );
215
216 return TRUE;
217 }
218
219 //-----------------------------------------------------------------------------
220 // "motion_notify_event" of m_mainWidget
221 //-----------------------------------------------------------------------------
222
223 static gint gtk_window_motion_notify_callback( GtkWidget *widget, GdkEventMotion *gdk_event, wxMiniFrame *win )
224 {
225 if (g_isIdle) wxapp_install_idle_handler();
226
227 if (!win->HasVMT()) return FALSE;
228 if (g_blockEventsOnDrag) return TRUE;
229 if (g_blockEventsOnScroll) return TRUE;
230
231 if (!win->m_isDragging) return TRUE;
232
233 if (gdk_event->is_hint)
234 {
235 int x = 0;
236 int y = 0;
237 GdkModifierType state;
238 gdk_window_get_pointer(gdk_event->window, &x, &y, &state);
239 gdk_event->x = x;
240 gdk_event->y = y;
241 gdk_event->state = state;
242 }
243
244 DrawFrame( widget, win->m_oldX, win->m_oldY, win->m_width, win->m_height );
245 win->m_oldX = (int)gdk_event->x - win->m_diffX;
246 win->m_oldY = (int)gdk_event->y - win->m_diffY;
247 DrawFrame( widget, win->m_oldX, win->m_oldY, win->m_width, win->m_height );
248
249 return TRUE;
250 }
251
252 //-----------------------------------------------------------------------------
253 // "clicked" of X system button
254 //-----------------------------------------------------------------------------
255
256 static void gtk_button_clicked_callback( GtkWidget *WXUNUSED(widget), wxMiniFrame *mf )
257 {
258 if (g_isIdle) wxapp_install_idle_handler();
259
260 mf->Close();
261 }
262
263 //-----------------------------------------------------------------------------
264 // wxMiniFrame
265 //-----------------------------------------------------------------------------
266
267 IMPLEMENT_DYNAMIC_CLASS(wxMiniFrame,wxFrame)
268
269 bool wxMiniFrame::Create( wxWindow *parent, wxWindowID id, const wxString &title,
270 const wxPoint &pos, const wxSize &size,
271 long style, const wxString &name )
272 {
273 style = style | wxSIMPLE_BORDER;
274
275 if ((style & wxCAPTION) || (style & wxTINY_CAPTION_HORIZ) || (style & wxTINY_CAPTION_VERT))
276 m_miniTitle = 13;
277
278 m_miniEdge = 3;
279 m_isDragging = FALSE;
280 m_oldX = -1;
281 m_oldY = -1;
282 m_diffX = 0;
283 m_diffY = 0;
284
285 wxFrame::Create( parent, id, title, pos, size, style, name );
286
287 if ((style & wxSYSTEM_MENU) &&
288 ((style & wxCAPTION) || (style & wxTINY_CAPTION_HORIZ) || (style & wxTINY_CAPTION_VERT)))
289 {
290 GtkWidget *close_button = gtk_button_new_with_label( "x" );
291
292 gtk_myfixed_put( GTK_MYFIXED(m_mainWidget), close_button, 4, 4 );
293 gtk_widget_set_usize( close_button, 12, 11 );
294
295 gtk_widget_show( close_button );
296
297 gtk_signal_connect( GTK_OBJECT(close_button), "clicked",
298 GTK_SIGNAL_FUNC(gtk_button_clicked_callback), (gpointer*)this );
299 }
300
301 /* these are called when the borders are drawn */
302 gtk_signal_connect( GTK_OBJECT(m_mainWidget), "expose_event",
303 GTK_SIGNAL_FUNC(gtk_window_own_expose_callback), (gpointer)this );
304
305 gtk_signal_connect( GTK_OBJECT(m_mainWidget), "draw",
306 GTK_SIGNAL_FUNC(gtk_window_own_draw_callback), (gpointer)this );
307
308 /* these are required for dragging the mini frame around */
309 gtk_signal_connect( GTK_OBJECT(m_mainWidget), "button_press_event",
310 GTK_SIGNAL_FUNC(gtk_window_button_press_callback), (gpointer)this );
311
312 gtk_signal_connect( GTK_OBJECT(m_mainWidget), "button_release_event",
313 GTK_SIGNAL_FUNC(gtk_window_button_release_callback), (gpointer)this );
314
315 gtk_signal_connect( GTK_OBJECT(m_mainWidget), "motion_notify_event",
316 GTK_SIGNAL_FUNC(gtk_window_motion_notify_callback), (gpointer)this );
317
318 return TRUE;
319 }