]> git.saurik.com Git - wxWidgets.git/blame - src/gtk1/toplevel.cpp
fixed crash on invalid data (patch 1039453)
[wxWidgets.git] / src / gtk1 / toplevel.cpp
CommitLineData
7d9f12f3
VS
1/////////////////////////////////////////////////////////////////////////////
2// Name: toplevel.cpp
3// Purpose:
4// Author: Robert Roebling
5// Id: $Id$
6// Copyright: (c) 1998 Robert Roebling
65571936 7// Licence: wxWindows licence
7d9f12f3
VS
8/////////////////////////////////////////////////////////////////////////////
9
10// ============================================================================
11// declarations
12// ============================================================================
13
14// ----------------------------------------------------------------------------
15// headers
16// ----------------------------------------------------------------------------
17
14f355c2 18#if defined(__GNUG__) && !defined(NO_GCC_PRAGMA)
7d9f12f3
VS
19 #pragma implementation "toplevel.h"
20#endif
21
14f355c2
VS
22// For compilers that support precompilation, includes "wx.h".
23#include "wx/wxprec.h"
24
7d9f12f3
VS
25#ifdef __VMS
26#define XIconifyWindow XICONIFYWINDOW
27#endif
28
29#include "wx/defs.h"
30
2b5f62a0 31#include "wx/log.h"
7d9f12f3
VS
32#include "wx/dialog.h"
33#include "wx/control.h"
34#include "wx/app.h"
35#include "wx/dcclient.h"
fab591c5 36#include "wx/gtk/private.h"
8166ab43 37#include "wx/timer.h"
ca06ee0d 38#include "wx/settings.h"
7d9f12f3
VS
39
40#include <glib.h>
41#include <gdk/gdk.h>
42#include <gtk/gtk.h>
43#include <gdk/gdkkeysyms.h>
44#include <gdk/gdkx.h>
45
46#include "wx/gtk/win_gtk.h"
47
f618020a
MB
48#include "wx/unix/utilsx11.h"
49
8a9650ea
RR
50// XA_CARDINAL
51#include <X11/Xatom.h>
52
7d9f12f3
VS
53// ----------------------------------------------------------------------------
54// idle system
55// ----------------------------------------------------------------------------
56
57extern void wxapp_install_idle_handler();
58extern bool g_isIdle;
7d9f12f3 59
7d9f12f3
VS
60// ----------------------------------------------------------------------------
61// data
62// ----------------------------------------------------------------------------
63
06fda9e8 64extern wxList wxPendingDelete;
d7fa7eaa 65
06fda9e8
RR
66extern int g_openDialogs;
67extern wxWindowGTK *g_delayedFocus;
68
69// the frame that is currently active (i.e. its child has focus). It is
70// used to generate wxActivateEvents
71static wxTopLevelWindowGTK *g_activeFrame = (wxTopLevelWindowGTK*) NULL;
72static wxTopLevelWindowGTK *g_lastActiveFrame = (wxTopLevelWindowGTK*) NULL;
73
74// if we detect that the app has got/lost the focus, we set this variable to
75// either TRUE or FALSE and an activate event will be sent during the next
76// OnIdle() call and it is reset to -1: this value means that we shouldn't
77// send any activate events at all
78static int g_sendActivateEvent = -1;
79
80//-----------------------------------------------------------------------------
81// "focus_in_event"
82//-----------------------------------------------------------------------------
83
84static gint gtk_frame_focus_in_callback( GtkWidget *widget,
85 GdkEvent *WXUNUSED(event),
86 wxTopLevelWindowGTK *win )
87{
88 if (g_isIdle)
89 wxapp_install_idle_handler();
90
91 switch ( g_sendActivateEvent )
92 {
93 case -1:
94 // we've got focus from outside, synthetize wxActivateEvent
95 g_sendActivateEvent = 1;
96 break;
97
98 case 0:
99 // another our window just lost focus, it was already ours before
100 // - don't send any wxActivateEvent
101 g_sendActivateEvent = -1;
102 break;
103 }
104
105 g_activeFrame = win;
106 g_lastActiveFrame = g_activeFrame;
107
108 // wxPrintf( wxT("active: %s\n"), win->GetTitle().c_str() );
109
110 wxLogTrace(wxT("activate"), wxT("Activating frame %p (from focus_in)"), g_activeFrame);
111 wxActivateEvent event(wxEVT_ACTIVATE, TRUE, g_activeFrame->GetId());
112 event.SetEventObject(g_activeFrame);
113 g_activeFrame->GetEventHandler()->ProcessEvent(event);
114
115 return TRUE;
116}
117
118//-----------------------------------------------------------------------------
119// "focus_out_event"
120//-----------------------------------------------------------------------------
121
122static gint gtk_frame_focus_out_callback( GtkWidget *widget,
123 GdkEventFocus *WXUNUSED(gdk_event),
124 wxTopLevelWindowGTK *win )
125{
126 if (g_isIdle)
127 wxapp_install_idle_handler();
128
129 // if the focus goes out of our app alltogether, OnIdle() will send
130 // wxActivateEvent, otherwise gtk_window_focus_in_callback() will reset
131 // g_sendActivateEvent to -1
132 g_sendActivateEvent = 0;
133
134 // wxASSERT_MSG( (g_activeFrame == win), wxT("TLW deactivatd although it wasn't active") );
135
136 // wxPrintf( wxT("inactive: %s\n"), win->GetTitle().c_str() );
137
138 wxLogTrace(wxT("activate"), wxT("Activating frame %p (from focus_in)"), g_activeFrame);
139 wxActivateEvent event(wxEVT_ACTIVATE, FALSE, g_activeFrame->GetId());
140 event.SetEventObject(g_activeFrame);
141 g_activeFrame->GetEventHandler()->ProcessEvent(event);
142
143 g_activeFrame = NULL;
144
145 return TRUE;
146}
7d9f12f3 147
7d9f12f3
VS
148//-----------------------------------------------------------------------------
149// "focus" from m_window
150//-----------------------------------------------------------------------------
151
152static gint gtk_frame_focus_callback( GtkWidget *widget, GtkDirectionType WXUNUSED(d), wxWindow *WXUNUSED(win) )
153{
154 if (g_isIdle)
155 wxapp_install_idle_handler();
156
157 // This disables GTK's tab traversal
158 gtk_signal_emit_stop_by_name( GTK_OBJECT(widget), "focus" );
159 return TRUE;
160}
161
162//-----------------------------------------------------------------------------
163// "size_allocate"
164//-----------------------------------------------------------------------------
165
166static void gtk_frame_size_callback( GtkWidget *WXUNUSED(widget), GtkAllocation* alloc, wxTopLevelWindowGTK *win )
167{
168 if (g_isIdle)
169 wxapp_install_idle_handler();
170
171 if (!win->m_hasVMT)
172 return;
173
174 if ((win->m_width != alloc->width) || (win->m_height != alloc->height))
175 {
176/*
177 wxPrintf( "OnSize from " );
178 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
179 wxPrintf( win->GetClassInfo()->GetClassName() );
180 wxPrintf( " %d %d %d %d\n", (int)alloc->x,
181 (int)alloc->y,
182 (int)alloc->width,
183 (int)alloc->height );
184*/
185
186 win->m_width = alloc->width;
187 win->m_height = alloc->height;
7d9f12f3
VS
188 win->GtkUpdateSize();
189 }
190}
191
192//-----------------------------------------------------------------------------
193// "delete_event"
194//-----------------------------------------------------------------------------
195
196static gint gtk_frame_delete_callback( GtkWidget *WXUNUSED(widget), GdkEvent *WXUNUSED(event), wxTopLevelWindowGTK *win )
197{
198 if (g_isIdle)
199 wxapp_install_idle_handler();
200
201 if (win->IsEnabled() &&
5152b0e5
JS
202 (g_openDialogs == 0 || (win->GetExtraStyle() & wxTOPLEVEL_EX_DIALOG) ||
203 win->IsGrabbed()))
7d9f12f3
VS
204 win->Close();
205
206 return TRUE;
207}
208
209
210//-----------------------------------------------------------------------------
211// "configure_event"
212//-----------------------------------------------------------------------------
213
214static gint
7d9f12f3 215gtk_frame_configure_callback( GtkWidget *WXUNUSED(widget), GdkEventConfigure *WXUNUSED(event), wxTopLevelWindowGTK *win )
7d9f12f3
VS
216{
217 if (g_isIdle)
218 wxapp_install_idle_handler();
219
48f72114 220 if (!win->m_hasVMT || !win->IsShown())
7d9f12f3
VS
221 return FALSE;
222
7d9f12f3
VS
223 int x = 0;
224 int y = 0;
225 gdk_window_get_root_origin( win->m_widget->window, &x, &y );
226 win->m_x = x;
227 win->m_y = y;
7d9f12f3
VS
228
229 wxMoveEvent mevent( wxPoint(win->m_x,win->m_y), win->GetId() );
230 mevent.SetEventObject( win );
231 win->GetEventHandler()->ProcessEvent( mevent );
232
233 return FALSE;
234}
235
236//-----------------------------------------------------------------------------
237// "realize" from m_widget
238//-----------------------------------------------------------------------------
239
e1f14d22
RR
240// we cannot MWM hints and icons before the widget has been realized,
241// so we do this directly after realization
7d9f12f3
VS
242
243static void
6aeb6f2a
VZ
244gtk_frame_realized_callback( GtkWidget * WXUNUSED(widget),
245 wxTopLevelWindowGTK *win )
7d9f12f3
VS
246{
247 if (g_isIdle)
248 wxapp_install_idle_handler();
249
e1f14d22
RR
250 // All this is for Motif Window Manager "hints" and is supposed to be
251 // recognized by other WM as well. Not tested.
82c9f85c 252 gdk_window_set_decorations(win->m_widget->window,
f819b4a3 253 (GdkWMDecoration)win->m_gdkDecor);
82c9f85c 254 gdk_window_set_functions(win->m_widget->window,
f819b4a3 255 (GdkWMFunction)win->m_gdkFunc);
7d9f12f3 256
e1f14d22 257 // GTK's shrinking/growing policy
f819b4a3 258 if ((win->m_gdkFunc & GDK_FUNC_RESIZE) == 0)
7d9f12f3
VS
259 gtk_window_set_policy(GTK_WINDOW(win->m_widget), 0, 0, 1);
260 else
261 gtk_window_set_policy(GTK_WINDOW(win->m_widget), 1, 1, 1);
262
e1f14d22 263 // reset the icon
7efaed4d 264 wxIconBundle iconsOld = win->GetIcons();
6aeb6f2a 265 if ( iconsOld.GetIcon(-1).Ok() )
7d9f12f3 266 {
7d9f12f3 267 win->SetIcon( wxNullIcon );
7efaed4d 268 win->SetIcons( iconsOld );
7d9f12f3 269 }
7d9f12f3
VS
270}
271
272//-----------------------------------------------------------------------------
273// "map_event" from m_widget
274//-----------------------------------------------------------------------------
275
276static void
277gtk_frame_map_callback( GtkWidget * WXUNUSED(widget),
278 GdkEvent * WXUNUSED(event),
279 wxTopLevelWindow *win )
280{
281 win->SetIconizeState(FALSE);
282}
283
284//-----------------------------------------------------------------------------
285// "unmap_event" from m_widget
286//-----------------------------------------------------------------------------
287
288static void
289gtk_frame_unmap_callback( GtkWidget * WXUNUSED(widget),
290 GdkEvent * WXUNUSED(event),
291 wxTopLevelWindow *win )
292{
293 win->SetIconizeState(TRUE);
294}
295
296//-----------------------------------------------------------------------------
297// "expose_event" of m_client
298//-----------------------------------------------------------------------------
299
300static int gtk_window_expose_callback( GtkWidget *widget, GdkEventExpose *gdk_event, wxWindow *win )
301{
302 GtkPizza *pizza = GTK_PIZZA(widget);
303
90350682
VZ
304 gtk_paint_flat_box (win->m_widget->style,
305 pizza->bin_window, GTK_STATE_NORMAL,
306 GTK_SHADOW_NONE,
307 &gdk_event->area,
308 win->m_widget,
309 (char *)"base",
310 0, 0, -1, -1);
7d9f12f3 311
cba9ef7f 312 return FALSE;
7d9f12f3
VS
313}
314
315//-----------------------------------------------------------------------------
316// "draw" of m_client
317//-----------------------------------------------------------------------------
318
52d6235d 319#ifndef __WXGTK20__
7d9f12f3
VS
320
321static void gtk_window_draw_callback( GtkWidget *widget, GdkRectangle *rect, wxWindow *win )
322{
323 GtkPizza *pizza = GTK_PIZZA(widget);
324
90350682
VZ
325 gtk_paint_flat_box (win->m_widget->style,
326 pizza->bin_window, GTK_STATE_NORMAL,
327 GTK_SHADOW_NONE,
328 rect,
329 win->m_widget,
330 (char *)"base",
331 0, 0, -1, -1);
7d9f12f3
VS
332}
333
52d6235d
VZ
334#endif // GTK+ 1.x
335
7d9f12f3
VS
336// ----------------------------------------------------------------------------
337// wxTopLevelWindowGTK itself
338// ----------------------------------------------------------------------------
339
340//-----------------------------------------------------------------------------
341// InsertChild for wxTopLevelWindowGTK
342//-----------------------------------------------------------------------------
343
344/* Callback for wxTopLevelWindowGTK. This very strange beast has to be used because
345 * C++ has no virtual methods in a constructor. We have to emulate a
77ffb593 346 * virtual function here as wxWidgets requires different ways to insert
7d9f12f3
VS
347 * a child in container classes. */
348
349static void wxInsertChildInTopLevelWindow( wxTopLevelWindowGTK* parent, wxWindow* child )
350{
351 wxASSERT( GTK_IS_WIDGET(child->m_widget) );
352
353 if (!parent->m_insertInClientArea)
354 {
e1f14d22 355 // these are outside the client area
7d9f12f3
VS
356 wxTopLevelWindowGTK* frame = (wxTopLevelWindowGTK*) parent;
357 gtk_pizza_put( GTK_PIZZA(frame->m_mainWidget),
358 GTK_WIDGET(child->m_widget),
359 child->m_x,
360 child->m_y,
361 child->m_width,
362 child->m_height );
363 }
364 else
365 {
e1f14d22 366 // these are inside the client area
7d9f12f3
VS
367 gtk_pizza_put( GTK_PIZZA(parent->m_wxwindow),
368 GTK_WIDGET(child->m_widget),
e4b7b2b0
VS
369 child->m_x,
370 child->m_y,
7d9f12f3
VS
371 child->m_width,
372 child->m_height );
373 }
374
e1f14d22 375 // resize on OnInternalIdle
7d9f12f3
VS
376 parent->GtkUpdateSize();
377}
378
379// ----------------------------------------------------------------------------
380// wxTopLevelWindowGTK creation
381// ----------------------------------------------------------------------------
382
383void wxTopLevelWindowGTK::Init()
384{
385 m_sizeSet = FALSE;
386 m_miniEdge = 0;
387 m_miniTitle = 0;
388 m_mainWidget = (GtkWidget*) NULL;
389 m_insertInClientArea = TRUE;
7d9f12f3
VS
390 m_isIconized = FALSE;
391 m_fsIsShowing = FALSE;
392 m_themeEnabled = TRUE;
f819b4a3 393 m_gdkDecor = m_gdkFunc = 0;
5152b0e5 394 m_grabbed = FALSE;
7d9f12f3
VS
395}
396
397bool wxTopLevelWindowGTK::Create( wxWindow *parent,
f819b4a3
VS
398 wxWindowID id,
399 const wxString& title,
400 const wxPoint& pos,
401 const wxSize& sizeOrig,
402 long style,
403 const wxString &name )
7d9f12f3
VS
404{
405 // always create a frame of some reasonable, even if arbitrary, size (at
406 // least for MSW compatibility)
407 wxSize size = sizeOrig;
1111cedc 408 size.x = WidthDefault(size.x);
66202a7e 409 size.y = HeightDefault(size.y);
7d9f12f3
VS
410
411 wxTopLevelWindows.Append( this );
412
413 m_needParent = FALSE;
6aeb6f2a 414
7d9f12f3
VS
415 if (!PreCreation( parent, pos, size ) ||
416 !CreateBase( parent, id, pos, size, style, wxDefaultValidator, name ))
417 {
418 wxFAIL_MSG( wxT("wxTopLevelWindowGTK creation failed") );
419 return FALSE;
420 }
421
422 m_title = title;
423
424 m_insertCallback = (wxInsertChildFunction) wxInsertChildInTopLevelWindow;
425
63c5efa3
VS
426 // NB: m_widget may be !=NULL if it was created by derived class' Create,
427 // e.g. in wxTaskBarIconAreaGTK
428 if (m_widget == NULL)
429 {
430 GtkWindowType win_type = GTK_WINDOW_TOPLEVEL;
63c5efa3
VS
431 if (style & wxFRAME_TOOL_WINDOW)
432 win_type = GTK_WINDOW_POPUP;
82c9f85c 433
63c5efa3
VS
434 if (GetExtraStyle() & wxTOPLEVEL_EX_DIALOG)
435 {
9e691f46 436#ifdef __WXGTK20__
4d8d6490
VS
437 m_widget = gtk_window_new(GTK_WINDOW_TOPLEVEL);
438 // Tell WM that this is a dialog window and make it center
439 // on parent by default (this is what GtkDialog ctor does):
440 gtk_window_set_type_hint(GTK_WINDOW(m_widget),
441 GDK_WINDOW_TYPE_HINT_DIALOG);
442 gtk_window_set_position(GTK_WINDOW(m_widget),
443 GTK_WIN_POS_CENTER_ON_PARENT);
9e691f46 444#else
4d8d6490 445 m_widget = gtk_window_new(GTK_WINDOW_DIALOG);
9e691f46 446#endif
63c5efa3 447 }
4d8d6490
VS
448 else
449 {
450 m_widget = gtk_window_new(win_type);
451 }
63c5efa3 452 }
7d9f12f3 453
50819679
JS
454 if (m_parent && (((GTK_IS_WINDOW(m_parent->m_widget)) &&
455 (GetExtraStyle() & wxTOPLEVEL_EX_DIALOG)) ||
456 (style & wxFRAME_FLOAT_ON_PARENT)))
7cd95599 457 {
7d9f12f3 458 gtk_window_set_transient_for( GTK_WINDOW(m_widget), GTK_WINDOW(m_parent->m_widget) );
7cd95599 459 }
7d9f12f3 460
2be125e6
VS
461#if GTK_CHECK_VERSION(2,2,0)
462 if (style & wxFRAME_NO_TASKBAR)
463 {
464 gtk_window_set_skip_taskbar_hint(GTK_WINDOW(m_widget), TRUE);
465 }
466#endif
467
7d9f12f3 468 if (!name.IsEmpty())
fab591c5 469 gtk_window_set_wmclass( GTK_WINDOW(m_widget), wxGTK_CONV( name ), wxGTK_CONV( name ) );
7d9f12f3 470
fab591c5 471 gtk_window_set_title( GTK_WINDOW(m_widget), wxGTK_CONV( title ) );
7d9f12f3
VS
472 GTK_WIDGET_UNSET_FLAGS( m_widget, GTK_CAN_FOCUS );
473
474 gtk_signal_connect( GTK_OBJECT(m_widget), "delete_event",
475 GTK_SIGNAL_FUNC(gtk_frame_delete_callback), (gpointer)this );
476
e1f14d22 477 // m_mainWidget holds the toolbar, the menubar and the client area
7d9f12f3
VS
478 m_mainWidget = gtk_pizza_new();
479 gtk_widget_show( m_mainWidget );
480 GTK_WIDGET_UNSET_FLAGS( m_mainWidget, GTK_CAN_FOCUS );
481 gtk_container_add( GTK_CONTAINER(m_widget), m_mainWidget );
482
cba9ef7f
RR
483 if (m_miniEdge == 0) // wxMiniFrame has its own version.
484 {
485 // For m_mainWidget themes
486 gtk_signal_connect( GTK_OBJECT(m_mainWidget), "expose_event",
7d9f12f3 487 GTK_SIGNAL_FUNC(gtk_window_expose_callback), (gpointer)this );
4e5a4c69 488#ifndef __WXGTK20__
cba9ef7f 489 gtk_signal_connect( GTK_OBJECT(m_mainWidget), "draw",
7d9f12f3 490 GTK_SIGNAL_FUNC(gtk_window_draw_callback), (gpointer)this );
4e5a4c69 491#endif
cba9ef7f 492 }
7d9f12f3 493
e1f14d22 494 // m_wxwindow only represents the client area without toolbar and menubar
7d9f12f3
VS
495 m_wxwindow = gtk_pizza_new();
496 gtk_widget_show( m_wxwindow );
497 gtk_container_add( GTK_CONTAINER(m_mainWidget), m_wxwindow );
498
e1f14d22
RR
499 // we donm't allow the frame to get the focus as otherwise
500 // the frame will grab it at arbitrary focus changes
7d9f12f3
VS
501 GTK_WIDGET_UNSET_FLAGS( m_wxwindow, GTK_CAN_FOCUS );
502
503 if (m_parent) m_parent->AddChild( this );
504
e1f14d22 505 // the user resized the frame by dragging etc.
7d9f12f3
VS
506 gtk_signal_connect( GTK_OBJECT(m_widget), "size_allocate",
507 GTK_SIGNAL_FUNC(gtk_frame_size_callback), (gpointer)this );
508
509 PostCreation();
510
511 if ((m_x != -1) || (m_y != -1))
512 gtk_widget_set_uposition( m_widget, m_x, m_y );
6aeb6f2a 513
e1f14d22 514 gtk_window_set_default_size( GTK_WINDOW(m_widget), m_width, m_height );
7d9f12f3 515
e1f14d22
RR
516 // we cannot set MWM hints and icons before the widget has
517 // been realized, so we do this directly after realization
7d9f12f3
VS
518 gtk_signal_connect( GTK_OBJECT(m_widget), "realize",
519 GTK_SIGNAL_FUNC(gtk_frame_realized_callback), (gpointer) this );
520
e1f14d22 521 // the only way to get the window size is to connect to this event
7d9f12f3
VS
522 gtk_signal_connect( GTK_OBJECT(m_widget), "configure_event",
523 GTK_SIGNAL_FUNC(gtk_frame_configure_callback), (gpointer)this );
524
e1f14d22 525 // map and unmap for iconized state
7d9f12f3
VS
526 gtk_signal_connect( GTK_OBJECT(m_widget), "map_event",
527 GTK_SIGNAL_FUNC(gtk_frame_map_callback), (gpointer)this );
528 gtk_signal_connect( GTK_OBJECT(m_widget), "unmap_event",
529 GTK_SIGNAL_FUNC(gtk_frame_unmap_callback), (gpointer)this );
530
e1f14d22 531 // the only way to get the window size is to connect to this event
7d9f12f3
VS
532 gtk_signal_connect( GTK_OBJECT(m_widget), "configure_event",
533 GTK_SIGNAL_FUNC(gtk_frame_configure_callback), (gpointer)this );
534
e1f14d22 535 // disable native tab traversal
7d9f12f3
VS
536 gtk_signal_connect( GTK_OBJECT(m_widget), "focus",
537 GTK_SIGNAL_FUNC(gtk_frame_focus_callback), (gpointer)this );
538
06fda9e8
RR
539 // activation
540 gtk_signal_connect( GTK_OBJECT(m_widget), "focus_in_event",
541 GTK_SIGNAL_FUNC(gtk_frame_focus_in_callback), (gpointer)this );
542 gtk_signal_connect( GTK_OBJECT(m_widget), "focus_out_event",
543 GTK_SIGNAL_FUNC(gtk_frame_focus_out_callback), (gpointer)this );
544
e1f14d22 545 // decorations
f819b4a3
VS
546 if ((m_miniEdge > 0) || (style & wxSIMPLE_BORDER) || (style & wxNO_BORDER))
547 {
548 m_gdkDecor = 0;
549 m_gdkFunc = 0;
550 }
551 else
552 {
553 m_gdkDecor = (long) GDK_DECOR_BORDER;
554 m_gdkFunc = (long) GDK_FUNC_MOVE;
82c9f85c 555
f819b4a3 556 // All this is for Motif Window Manager "hints" and is supposed to be
e1f14d22 557 // recognized by other WMs as well.
f819b4a3 558 if ((style & wxCAPTION) != 0)
c3d8ee42 559 {
f819b4a3 560 m_gdkDecor |= GDK_DECOR_TITLE;
c3d8ee42 561 }
850c6ed4 562 if ((style & wxCLOSE_BOX) != 0)
f819b4a3
VS
563 {
564 m_gdkFunc |= GDK_FUNC_CLOSE;
c3d8ee42
VS
565 }
566 if ((style & wxSYSTEM_MENU) != 0)
567 {
f819b4a3
VS
568 m_gdkDecor |= GDK_DECOR_MENU;
569 }
570 if ((style & wxMINIMIZE_BOX) != 0)
571 {
572 m_gdkFunc |= GDK_FUNC_MINIMIZE;
573 m_gdkDecor |= GDK_DECOR_MINIMIZE;
574 }
575 if ((style & wxMAXIMIZE_BOX) != 0)
576 {
577 m_gdkFunc |= GDK_FUNC_MAXIMIZE;
578 m_gdkDecor |= GDK_DECOR_MAXIMIZE;
579 }
580 if ((style & wxRESIZE_BORDER) != 0)
581 {
582 m_gdkFunc |= GDK_FUNC_RESIZE;
583 m_gdkDecor |= GDK_DECOR_RESIZEH;
584 }
585 }
586
7d9f12f3
VS
587 return TRUE;
588}
589
590wxTopLevelWindowGTK::~wxTopLevelWindowGTK()
591{
5152b0e5
JS
592 if (m_grabbed)
593 {
83afe211 594 wxASSERT_MSG( FALSE, _T("Window still grabbed"));
5152b0e5
JS
595 RemoveGrab();
596 }
1cbee0b4 597
7d9f12f3 598 m_isBeingDeleted = TRUE;
6aeb6f2a 599
710968c3
VZ
600 // it may also be GtkScrolledWindow in the case of an MDI child
601 if (GTK_IS_WINDOW(m_widget))
602 {
603 gtk_window_set_focus( GTK_WINDOW(m_widget), NULL );
604 }
06fda9e8
RR
605
606 if (g_activeFrame == this)
607 g_activeFrame = NULL;
608 if (g_lastActiveFrame == this)
609 g_lastActiveFrame = NULL;
7d9f12f3
VS
610}
611
8a9650ea 612
8a9650ea 613
7d9f12f3
VS
614bool wxTopLevelWindowGTK::ShowFullScreen(bool show, long style )
615{
616 if (show == m_fsIsShowing) return FALSE; // return what?
617
618 m_fsIsShowing = show;
619
8166ab43 620 GdkWindow *window = m_widget->window;
1542ea39 621 wxX11FullScreenMethod method =
8166ab43
VS
622 wxGetFullScreenMethodX11((WXDisplay*)GDK_DISPLAY(),
623 (WXWindow)GDK_ROOT_WINDOW());
1542ea39 624
7d9f12f3
VS
625 if (show)
626 {
7d9f12f3
VS
627 m_fsSaveFlag = style;
628 GetPosition( &m_fsSaveFrame.x, &m_fsSaveFrame.y );
629 GetSize( &m_fsSaveFrame.width, &m_fsSaveFrame.height );
630
8a9650ea
RR
631 int screen_width,screen_height;
632 wxDisplaySize( &screen_width, &screen_height );
1cbee0b4 633
8a9650ea
RR
634 gint client_x, client_y, root_x, root_y;
635 gint width, height;
7d9f12f3 636
1cff04de 637 if (method != wxX11_FS_WMSPEC)
8166ab43
VS
638 {
639 // don't do it always, Metacity hates it
640 m_fsSaveGdkFunc = m_gdkFunc;
641 m_fsSaveGdkDecor = m_gdkDecor;
642 m_gdkFunc = m_gdkDecor = 0;
643 gdk_window_set_decorations(window, (GdkWMDecoration)0);
644 gdk_window_set_functions(window, (GdkWMFunction)0);
645 }
1542ea39 646
8a9650ea
RR
647 gdk_window_get_origin (m_widget->window, &root_x, &root_y);
648 gdk_window_get_geometry (m_widget->window, &client_x, &client_y,
649 &width, &height, NULL);
1cbee0b4 650
8a9650ea
RR
651 gdk_window_move_resize (m_widget->window, -client_x, -client_y,
652 screen_width + 1, screen_height + 1);
8166ab43
VS
653
654 wxSetFullScreenStateX11((WXDisplay*)GDK_DISPLAY(),
655 (WXWindow)GDK_ROOT_WINDOW(),
656 (WXWindow)GDK_WINDOW_XWINDOW(window),
657 show, &m_fsSaveFrame, method);
7d9f12f3
VS
658 }
659 else
660 {
1cff04de 661 if (method != wxX11_FS_WMSPEC)
8166ab43
VS
662 {
663 // don't do it always, Metacity hates it
664 m_gdkFunc = m_fsSaveGdkFunc;
665 m_gdkDecor = m_fsSaveGdkDecor;
666 gdk_window_set_decorations(window, (GdkWMDecoration)m_gdkDecor);
667 gdk_window_set_functions(window, (GdkWMFunction)m_gdkFunc);
668 }
1542ea39 669
8166ab43
VS
670 wxSetFullScreenStateX11((WXDisplay*)GDK_DISPLAY(),
671 (WXWindow)GDK_ROOT_WINDOW(),
672 (WXWindow)GDK_WINDOW_XWINDOW(window),
673 show, &m_fsSaveFrame, method);
1542ea39 674
8166ab43
VS
675 SetSize(m_fsSaveFrame.x, m_fsSaveFrame.y,
676 m_fsSaveFrame.width, m_fsSaveFrame.height);
7d9f12f3
VS
677 }
678
8166ab43 679
7d9f12f3
VS
680 return TRUE;
681}
682
683// ----------------------------------------------------------------------------
684// overridden wxWindow methods
685// ----------------------------------------------------------------------------
686
687bool wxTopLevelWindowGTK::Show( bool show )
688{
82b978d7 689 wxASSERT_MSG( (m_widget != NULL), wxT("invalid frame") );
7d9f12f3
VS
690
691 if (show && !m_sizeSet)
692 {
693 /* by calling GtkOnSize here, we don't have to call
694 either after showing the frame, which would entail
695 much ugly flicker or from within the size_allocate
696 handler, because GTK 1.1.X forbids that. */
697
698 GtkOnSize( m_x, m_y, m_width, m_height );
699 }
700
701 return wxWindow::Show( show );
702}
703
704void wxTopLevelWindowGTK::DoMoveWindow(int WXUNUSED(x), int WXUNUSED(y), int WXUNUSED(width), int WXUNUSED(height) )
705{
706 wxFAIL_MSG( wxT("DoMoveWindow called for wxTopLevelWindowGTK") );
707}
708
709void wxTopLevelWindowGTK::DoSetSize( int x, int y, int width, int height, int sizeFlags )
710{
82b978d7
RD
711 wxASSERT_MSG( (m_widget != NULL), wxT("invalid frame") );
712
e1f14d22 713 // this shouldn't happen: wxFrame, wxMDIParentFrame and wxMDIChildFrame have m_wxwindow
7d9f12f3
VS
714 wxASSERT_MSG( (m_wxwindow != NULL), wxT("invalid frame") );
715
e1f14d22 716 // avoid recursions
7d9f12f3
VS
717 if (m_resizing)
718 return;
719 m_resizing = TRUE;
720
721 int old_x = m_x;
722 int old_y = m_y;
723
724 int old_width = m_width;
725 int old_height = m_height;
726
727 if ((sizeFlags & wxSIZE_ALLOW_MINUS_ONE) == 0)
728 {
729 if (x != -1) m_x = x;
730 if (y != -1) m_y = y;
7d9f12f3
VS
731 }
732 else
733 {
734 m_x = x;
735 m_y = y;
7d9f12f3 736 }
d44c23ce
RR
737 if (width != -1) m_width = width;
738 if (height != -1) m_height = height;
7d9f12f3
VS
739
740/*
741 if ((sizeFlags & wxSIZE_AUTO_WIDTH) == wxSIZE_AUTO_WIDTH)
742 {
743 if (width == -1) m_width = 80;
744 }
745
746 if ((sizeFlags & wxSIZE_AUTO_HEIGHT) == wxSIZE_AUTO_HEIGHT)
747 {
748 if (height == -1) m_height = 26;
749 }
750*/
751
e7dda1ff
VS
752 int minWidth = GetMinWidth(),
753 minHeight = GetMinHeight(),
754 maxWidth = GetMaxWidth(),
755 maxHeight = GetMaxHeight();
756
62be94e1
RR
757#ifdef __WXGPE__
758 // GPE's window manager doesn't like size hints
759 // at all, esp. when the user has to use the
760 // virtual keyboard.
761 minWidth = -1;
762 minHeight = -1;
763 maxWidth = -1;
764 maxHeight = -1;
765#endif
ca06ee0d 766
e7dda1ff
VS
767 if ((minWidth != -1) && (m_width < minWidth)) m_width = minWidth;
768 if ((minHeight != -1) && (m_height < minHeight)) m_height = minHeight;
769 if ((maxWidth != -1) && (m_width > maxWidth)) m_width = maxWidth;
770 if ((maxHeight != -1) && (m_height > maxHeight)) m_height = maxHeight;
7d9f12f3
VS
771
772 if ((m_x != -1) || (m_y != -1))
773 {
774 if ((m_x != old_x) || (m_y != old_y))
775 {
776 gtk_widget_set_uposition( m_widget, m_x, m_y );
777 }
778 }
779
780 if ((m_width != old_width) || (m_height != old_height))
781 {
e1f14d22
RR
782 if (m_widget->window)
783 gdk_window_resize( m_widget->window, m_width, m_height );
784 else
785 gtk_window_set_default_size( GTK_WINDOW(m_widget), m_width, m_height );
7d9f12f3
VS
786
787 /* we set the size in GtkOnSize, i.e. mostly the actual resizing is
788 done either directly before the frame is shown or in idle time
789 so that different calls to SetSize() don't lead to flicker. */
790 m_sizeSet = FALSE;
791 }
792
793 m_resizing = FALSE;
794}
795
796void wxTopLevelWindowGTK::DoGetClientSize( int *width, int *height ) const
797{
82b978d7
RD
798 wxASSERT_MSG( (m_widget != NULL), wxT("invalid frame") );
799
7d9f12f3
VS
800 wxWindow::DoGetClientSize( width, height );
801 if (height)
802 {
e1f14d22 803 // mini edge
7d9f12f3
VS
804 *height -= m_miniEdge*2 + m_miniTitle;
805 }
806 if (width)
807 {
808 *width -= m_miniEdge*2;
809 }
810}
811
812void wxTopLevelWindowGTK::DoSetClientSize( int width, int height )
813{
82b978d7 814 wxASSERT_MSG( (m_widget != NULL), wxT("invalid frame") );
7d9f12f3 815
82c9f85c 816 DoSetSize(-1, -1,
7d9f12f3
VS
817 width + m_miniEdge*2, height + m_miniEdge*2 + m_miniTitle, 0);
818}
819
820void wxTopLevelWindowGTK::GtkOnSize( int WXUNUSED(x), int WXUNUSED(y),
82c9f85c 821 int width, int height )
7d9f12f3
VS
822{
823 // due to a bug in gtk, x,y are always 0
824 // m_x = x;
825 // m_y = y;
826
e1f14d22 827 // avoid recursions
7d9f12f3
VS
828 if (m_resizing) return;
829 m_resizing = TRUE;
830
831 if ( m_wxwindow == NULL ) return;
832
833 m_width = width;
834 m_height = height;
835
0d53fc34 836 /* wxMDIChildFrame derives from wxFrame but it _is_ a wxWindow as it uses
7d9f12f3 837 wxWindow::Create to create it's GTK equivalent. m_mainWidget is only
0d53fc34 838 set in wxFrame::Create so it is used to check what kind of frame we
7d9f12f3
VS
839 have here. if m_mainWidget is NULL it is a wxMDIChildFrame and so we
840 skip the part which handles m_frameMenuBar, m_frameToolBar and (most
841 importantly) m_mainWidget */
842
e7dda1ff
VS
843 int minWidth = GetMinWidth(),
844 minHeight = GetMinHeight(),
845 maxWidth = GetMaxWidth(),
846 maxHeight = GetMaxHeight();
847
62be94e1
RR
848#ifdef __WXGPE__
849 // GPE's window manager doesn't like size hints
850 // at all, esp. when the user has to use the
851 // virtual keyboard.
852 minWidth = -1;
853 minHeight = -1;
854 maxWidth = -1;
855 maxHeight = -1;
856#endif
ca06ee0d 857
e7dda1ff
VS
858 if ((minWidth != -1) && (m_width < minWidth)) m_width = minWidth;
859 if ((minHeight != -1) && (m_height < minHeight)) m_height = minHeight;
860 if ((maxWidth != -1) && (m_width > maxWidth)) m_width = maxWidth;
861 if ((maxHeight != -1) && (m_height > maxHeight)) m_height = maxHeight;
7d9f12f3
VS
862
863 if (m_mainWidget)
864 {
e1f14d22 865 // set size hints
801225c1
RL
866 gint flag = 0; // GDK_HINT_POS;
867 GdkGeometry geom;
868
e7dda1ff
VS
869 if ((minWidth != -1) || (minHeight != -1)) flag |= GDK_HINT_MIN_SIZE;
870 if ((maxWidth != -1) || (maxHeight != -1)) flag |= GDK_HINT_MAX_SIZE;
801225c1 871
e7dda1ff
VS
872 geom.min_width = minWidth;
873 geom.min_height = minHeight;
801225c1
RL
874
875 // Because of the way we set GDK_HINT_MAX_SIZE above, if either of
876 // maxHeight or maxWidth is set, we must set them both, else the
877 // remaining -1 will be taken literally.
878
879 // I'm certain this also happens elsewhere, and is the probable
880 // cause of other such things as:
881 // Gtk-WARNING **: gtk_widget_size_allocate():
882 // attempt to allocate widget with width 65535 and height 600
883 // but I don't have time to track them all now..
1cbee0b4 884 //
801225c1
RL
885 // Really we need to encapulate all this height/width business and
886 // stop any old method from ripping at the members directly and
887 // scattering -1's without regard for who might resolve them later.
888
889 geom.max_width = ( maxHeight == -1 ) ? maxWidth
890 : ( maxWidth == -1 ) ? wxGetDisplaySize().GetWidth()
891 : maxWidth ;
892
893 geom.max_height = ( maxWidth == -1 ) ? maxHeight // ( == -1 here )
894 : ( maxHeight == -1 ) ? wxGetDisplaySize().GetHeight()
895 : maxHeight ;
896
7d9f12f3
VS
897 gtk_window_set_geometry_hints( GTK_WINDOW(m_widget),
898 (GtkWidget*) NULL,
899 &geom,
900 (GdkWindowHints) flag );
901
902 /* I revert back to wxGTK's original behaviour. m_mainWidget holds the
903 * menubar, the toolbar and the client area, which is represented by
904 * m_wxwindow.
905 * this hurts in the eye, but I don't want to call SetSize()
906 * because I don't want to call any non-native functions here. */
907
908 int client_x = m_miniEdge;
909 int client_y = m_miniEdge + m_miniTitle;
910 int client_w = m_width - 2*m_miniEdge;
911 int client_h = m_height - 2*m_miniEdge - m_miniTitle;
801225c1 912
7d9f12f3
VS
913 gtk_pizza_set_size( GTK_PIZZA(m_mainWidget),
914 m_wxwindow,
915 client_x, client_y, client_w, client_h );
916 }
917 else
918 {
e1f14d22
RR
919 // If there is no m_mainWidget between m_widget and m_wxwindow there
920 // is no need to set the size or position of m_wxwindow.
7d9f12f3
VS
921 }
922
923 m_sizeSet = TRUE;
924
925 // send size event to frame
926 wxSizeEvent event( wxSize(m_width,m_height), GetId() );
927 event.SetEventObject( this );
928 GetEventHandler()->ProcessEvent( event );
929
930 m_resizing = FALSE;
931}
932
933void wxTopLevelWindowGTK::OnInternalIdle()
934{
935 if (!m_sizeSet && GTK_WIDGET_REALIZED(m_wxwindow))
936 {
937 GtkOnSize( m_x, m_y, m_width, m_height );
938
939 // we'll come back later
940 if (g_isIdle)
941 wxapp_install_idle_handler();
942 return;
943 }
944
6aeb6f2a
VZ
945 // set the focus if not done yet and if we can already do it
946 if ( GTK_WIDGET_REALIZED(m_wxwindow) )
947 {
cc06fe74
MB
948 if ( g_delayedFocus &&
949 wxGetTopLevelParent((wxWindow*)g_delayedFocus) == this )
6aeb6f2a 950 {
2b5f62a0
VZ
951 wxLogTrace(_T("focus"),
952 _T("Setting focus from wxTLW::OnIdle() to %s(%s)"),
953 g_delayedFocus->GetClassInfo()->GetClassName(),
954 g_delayedFocus->GetLabel().c_str());
955
6aeb6f2a
VZ
956 g_delayedFocus->SetFocus();
957 g_delayedFocus = NULL;
958 }
959 }
960
7d9f12f3 961 wxWindow::OnInternalIdle();
06fda9e8
RR
962
963 // Synthetize activate events.
964 if ( g_sendActivateEvent != -1 )
965 {
966 bool activate = g_sendActivateEvent != 0;
967
968 // do it only once
969 g_sendActivateEvent = -1;
970
971 wxTheApp->SetActive(activate, (wxWindow *)g_lastActiveFrame);
972 }
7d9f12f3
VS
973}
974
7d9f12f3
VS
975// ----------------------------------------------------------------------------
976// frame title/icon
977// ----------------------------------------------------------------------------
978
979void wxTopLevelWindowGTK::SetTitle( const wxString &title )
980{
82b978d7
RD
981 wxASSERT_MSG( (m_widget != NULL), wxT("invalid frame") );
982
7d9f12f3 983 m_title = title;
fab591c5 984 gtk_window_set_title( GTK_WINDOW(m_widget), wxGTK_CONV( title ) );
7d9f12f3
VS
985}
986
f618020a
MB
987void wxTopLevelWindowGTK::SetIcon( const wxIcon &icon )
988{
989 SetIcons( wxIconBundle( icon ) );
990}
991
992void wxTopLevelWindowGTK::SetIcons( const wxIconBundle &icons )
993{
82b978d7 994 wxASSERT_MSG( (m_widget != NULL), wxT("invalid frame") );
f618020a
MB
995
996 wxTopLevelWindowBase::SetIcons( icons );
997
87e53e2a
VS
998#ifdef __WXGTK20__
999 GList *list = NULL;
1000 size_t max = icons.m_icons.GetCount();
1001
1002 for (size_t i = 0; i < max; i++)
52d6235d 1003 {
87e53e2a
VS
1004 if (icons.m_icons[i].Ok())
1005 {
1006 list = g_list_prepend(list, icons.m_icons[i].GetPixbuf());
1007 }
1008 }
1009 gtk_window_set_icon_list(GTK_WINDOW(m_widget), list);
1010 g_list_free(list);
1011
1012#else // !__WXGTK20__
1013 GdkWindow* window = m_widget->window;
1014 if (!window)
1015 return;
1016
1017 wxIcon icon = icons.GetIcon(-1);
1018 if (icon.Ok())
1019 {
1020 wxMask *mask = icon.GetMask();
1021 GdkBitmap *bm = (GdkBitmap *) NULL;
1022 if (mask) bm = mask->GetBitmap();
1023
1024 gdk_window_set_icon( m_widget->window, (GdkWindow *) NULL, icon.GetPixmap(), bm );
52d6235d 1025 }
87e53e2a
VS
1026
1027 wxSetIconsX11( (WXDisplay*)GDK_WINDOW_XDISPLAY( window ),
1028 (WXWindow)GDK_WINDOW_XWINDOW( window ), icons );
1029#endif // !__WXGTK20__
f618020a
MB
1030}
1031
7d9f12f3
VS
1032// ----------------------------------------------------------------------------
1033// frame state: maximized/iconized/normal
1034// ----------------------------------------------------------------------------
1035
8805e155 1036void wxTopLevelWindowGTK::Maximize(bool maximize)
7d9f12f3 1037{
8805e155
RR
1038#ifdef __WXGTK20__
1039 if (maximize)
1040 gtk_window_maximize( GTK_WINDOW( m_widget ) );
1041 else
1042 gtk_window_unmaximize( GTK_WINDOW( m_widget ) );
1043#else
7d9f12f3 1044 wxFAIL_MSG( _T("not implemented") );
8805e155 1045#endif
7d9f12f3
VS
1046}
1047
1048bool wxTopLevelWindowGTK::IsMaximized() const
1049{
d8e1fe80
VS
1050#ifdef __WXGTK20__
1051 if(!m_widget->window)
1052 return false;
1053
1054 return gdk_window_get_state(m_widget->window) & GDK_WINDOW_STATE_MAXIMIZED;
1055#else
7d9f12f3
VS
1056 // wxFAIL_MSG( _T("not implemented") );
1057
1058 // This is an approximation
1059 return FALSE;
d8e1fe80 1060#endif
7d9f12f3
VS
1061}
1062
1063void wxTopLevelWindowGTK::Restore()
1064{
387fd89d 1065#ifdef __WXGTK20__
8805e155
RR
1066 // "Present" seems similar enough to "restore"
1067 gtk_window_present( GTK_WINDOW( m_widget ) );
1068#else
7d9f12f3 1069 wxFAIL_MSG( _T("not implemented") );
8805e155 1070#endif
7d9f12f3
VS
1071}
1072
1073void wxTopLevelWindowGTK::Iconize( bool iconize )
1074{
8805e155
RR
1075#ifdef __WXGTK20__
1076 if (iconize)
1077 gtk_window_iconify( GTK_WINDOW( m_widget ) );
1078 else
1079 gtk_window_deiconify( GTK_WINDOW( m_widget ) );
1080#else
7d9f12f3
VS
1081 if (iconize)
1082 {
1083 GdkWindow *window = m_widget->window;
1084
1085 // you should do it later, for example from OnCreate() handler
1086 wxCHECK_RET( window, _T("frame not created yet - can't iconize") );
1087
1088 XIconifyWindow( GDK_WINDOW_XDISPLAY( window ),
1089 GDK_WINDOW_XWINDOW( window ),
1090 DefaultScreen( GDK_DISPLAY() ) );
1091 }
8805e155 1092#endif
7d9f12f3
VS
1093}
1094
1095bool wxTopLevelWindowGTK::IsIconized() const
1096{
1097 return m_isIconized;
1098}
1099
1100void wxTopLevelWindowGTK::SetIconizeState(bool iconize)
1101{
1102 if ( iconize != m_isIconized )
1103 {
1104 m_isIconized = iconize;
1105 (void)SendIconizeEvent(iconize);
1106 }
1107}
1108
5152b0e5
JS
1109void wxTopLevelWindowGTK::AddGrab()
1110{
1111 if (!m_grabbed)
1112 {
1113 m_grabbed = TRUE;
1114 gtk_grab_add( m_widget );
1115 gtk_main();
1116 gtk_grab_remove( m_widget );
1117 }
1118}
1119
1120void wxTopLevelWindowGTK::RemoveGrab()
1121{
1122 if (m_grabbed)
1123 {
1124 gtk_main_quit();
1125 m_grabbed = FALSE;
1126 }
1127}
801225c1 1128
1542ea39
RD
1129
1130// helper
1131static bool do_shape_combine_region(GdkWindow* window, const wxRegion& region)
1132{
1133 if (window)
1134 {
1135 if (region.IsEmpty())
1136 {
1137 gdk_window_shape_combine_mask(window, NULL, 0, 0);
1138 }
1139 else
1140 {
1141#ifdef __WXGTK20__
1142 gdk_window_shape_combine_region(window, region.GetRegion(), 0, 0);
1143#else
1144 wxBitmap bmp = region.ConvertToBitmap();
819451b6 1145 bmp.SetMask(new wxMask(bmp, *wxBLACK));
1542ea39
RD
1146 GdkBitmap* mask = bmp.GetMask()->GetBitmap();
1147 gdk_window_shape_combine_mask(window, mask, 0, 0);
1148#endif
1149 return TRUE;
1150 }
1151 }
1152 return FALSE;
1153}
1154
1155
1156bool wxTopLevelWindowGTK::SetShape(const wxRegion& region)
1157{
6a7e6411
RD
1158 wxCHECK_MSG( HasFlag(wxFRAME_SHAPED), FALSE,
1159 _T("Shaped windows must be created with the wxFRAME_SHAPED style."));
1160
1542ea39
RD
1161 GdkWindow *window = NULL;
1162 if (m_wxwindow)
1163 {
1164 window = GTK_PIZZA(m_wxwindow)->bin_window;
1165 do_shape_combine_region(window, region);
1166 }
1167 window = m_widget->window;
1168 return do_shape_combine_region(window, region);
1169}
1170
6b30a44e 1171bool wxTopLevelWindowGTK::IsActive()
35ff90a0 1172{
06fda9e8 1173 return (this == (wxTopLevelWindowGTK*)g_activeFrame);
35ff90a0
RR
1174}
1175