]> git.saurik.com Git - wxWidgets.git/blame - src/gtk/toplevel.cpp
small optimization in wxConfigPathChanger: don't change the path if it is already...
[wxWidgets.git] / src / gtk / 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
e25c7537
VS
454 wxWindow *topParent = wxGetTopLevelParent(m_parent);
455 if (topParent && (((GTK_IS_WINDOW(topParent->m_widget)) &&
50819679
JS
456 (GetExtraStyle() & wxTOPLEVEL_EX_DIALOG)) ||
457 (style & wxFRAME_FLOAT_ON_PARENT)))
7cd95599 458 {
e25c7537
VS
459 gtk_window_set_transient_for( GTK_WINDOW(m_widget),
460 GTK_WINDOW(topParent->m_widget) );
7cd95599 461 }
7d9f12f3 462
2be125e6
VS
463#if GTK_CHECK_VERSION(2,2,0)
464 if (style & wxFRAME_NO_TASKBAR)
465 {
466 gtk_window_set_skip_taskbar_hint(GTK_WINDOW(m_widget), TRUE);
467 }
468#endif
469
7d9f12f3 470 if (!name.IsEmpty())
fab591c5 471 gtk_window_set_wmclass( GTK_WINDOW(m_widget), wxGTK_CONV( name ), wxGTK_CONV( name ) );
7d9f12f3 472
fab591c5 473 gtk_window_set_title( GTK_WINDOW(m_widget), wxGTK_CONV( title ) );
7d9f12f3
VS
474 GTK_WIDGET_UNSET_FLAGS( m_widget, GTK_CAN_FOCUS );
475
476 gtk_signal_connect( GTK_OBJECT(m_widget), "delete_event",
477 GTK_SIGNAL_FUNC(gtk_frame_delete_callback), (gpointer)this );
478
e1f14d22 479 // m_mainWidget holds the toolbar, the menubar and the client area
7d9f12f3
VS
480 m_mainWidget = gtk_pizza_new();
481 gtk_widget_show( m_mainWidget );
482 GTK_WIDGET_UNSET_FLAGS( m_mainWidget, GTK_CAN_FOCUS );
483 gtk_container_add( GTK_CONTAINER(m_widget), m_mainWidget );
484
cba9ef7f
RR
485 if (m_miniEdge == 0) // wxMiniFrame has its own version.
486 {
487 // For m_mainWidget themes
488 gtk_signal_connect( GTK_OBJECT(m_mainWidget), "expose_event",
7d9f12f3 489 GTK_SIGNAL_FUNC(gtk_window_expose_callback), (gpointer)this );
4e5a4c69 490#ifndef __WXGTK20__
cba9ef7f 491 gtk_signal_connect( GTK_OBJECT(m_mainWidget), "draw",
7d9f12f3 492 GTK_SIGNAL_FUNC(gtk_window_draw_callback), (gpointer)this );
4e5a4c69 493#endif
cba9ef7f 494 }
7d9f12f3 495
e1f14d22 496 // m_wxwindow only represents the client area without toolbar and menubar
7d9f12f3
VS
497 m_wxwindow = gtk_pizza_new();
498 gtk_widget_show( m_wxwindow );
499 gtk_container_add( GTK_CONTAINER(m_mainWidget), m_wxwindow );
500
e1f14d22
RR
501 // we donm't allow the frame to get the focus as otherwise
502 // the frame will grab it at arbitrary focus changes
7d9f12f3
VS
503 GTK_WIDGET_UNSET_FLAGS( m_wxwindow, GTK_CAN_FOCUS );
504
505 if (m_parent) m_parent->AddChild( this );
506
e1f14d22 507 // the user resized the frame by dragging etc.
7d9f12f3
VS
508 gtk_signal_connect( GTK_OBJECT(m_widget), "size_allocate",
509 GTK_SIGNAL_FUNC(gtk_frame_size_callback), (gpointer)this );
510
511 PostCreation();
512
513 if ((m_x != -1) || (m_y != -1))
514 gtk_widget_set_uposition( m_widget, m_x, m_y );
6aeb6f2a 515
e1f14d22 516 gtk_window_set_default_size( GTK_WINDOW(m_widget), m_width, m_height );
7d9f12f3 517
e1f14d22
RR
518 // we cannot set MWM hints and icons before the widget has
519 // been realized, so we do this directly after realization
7d9f12f3
VS
520 gtk_signal_connect( GTK_OBJECT(m_widget), "realize",
521 GTK_SIGNAL_FUNC(gtk_frame_realized_callback), (gpointer) this );
522
e1f14d22 523 // the only way to get the window size is to connect to this event
7d9f12f3
VS
524 gtk_signal_connect( GTK_OBJECT(m_widget), "configure_event",
525 GTK_SIGNAL_FUNC(gtk_frame_configure_callback), (gpointer)this );
526
e1f14d22 527 // map and unmap for iconized state
7d9f12f3
VS
528 gtk_signal_connect( GTK_OBJECT(m_widget), "map_event",
529 GTK_SIGNAL_FUNC(gtk_frame_map_callback), (gpointer)this );
530 gtk_signal_connect( GTK_OBJECT(m_widget), "unmap_event",
531 GTK_SIGNAL_FUNC(gtk_frame_unmap_callback), (gpointer)this );
532
e1f14d22 533 // the only way to get the window size is to connect to this event
7d9f12f3
VS
534 gtk_signal_connect( GTK_OBJECT(m_widget), "configure_event",
535 GTK_SIGNAL_FUNC(gtk_frame_configure_callback), (gpointer)this );
536
e1f14d22 537 // disable native tab traversal
7d9f12f3
VS
538 gtk_signal_connect( GTK_OBJECT(m_widget), "focus",
539 GTK_SIGNAL_FUNC(gtk_frame_focus_callback), (gpointer)this );
540
06fda9e8
RR
541 // activation
542 gtk_signal_connect( GTK_OBJECT(m_widget), "focus_in_event",
543 GTK_SIGNAL_FUNC(gtk_frame_focus_in_callback), (gpointer)this );
544 gtk_signal_connect( GTK_OBJECT(m_widget), "focus_out_event",
545 GTK_SIGNAL_FUNC(gtk_frame_focus_out_callback), (gpointer)this );
546
e1f14d22 547 // decorations
f819b4a3
VS
548 if ((m_miniEdge > 0) || (style & wxSIMPLE_BORDER) || (style & wxNO_BORDER))
549 {
550 m_gdkDecor = 0;
551 m_gdkFunc = 0;
552 }
553 else
554 {
555 m_gdkDecor = (long) GDK_DECOR_BORDER;
556 m_gdkFunc = (long) GDK_FUNC_MOVE;
82c9f85c 557
f819b4a3 558 // All this is for Motif Window Manager "hints" and is supposed to be
e1f14d22 559 // recognized by other WMs as well.
f819b4a3 560 if ((style & wxCAPTION) != 0)
c3d8ee42 561 {
f819b4a3 562 m_gdkDecor |= GDK_DECOR_TITLE;
c3d8ee42 563 }
850c6ed4 564 if ((style & wxCLOSE_BOX) != 0)
f819b4a3
VS
565 {
566 m_gdkFunc |= GDK_FUNC_CLOSE;
c3d8ee42
VS
567 }
568 if ((style & wxSYSTEM_MENU) != 0)
569 {
f819b4a3
VS
570 m_gdkDecor |= GDK_DECOR_MENU;
571 }
572 if ((style & wxMINIMIZE_BOX) != 0)
573 {
574 m_gdkFunc |= GDK_FUNC_MINIMIZE;
575 m_gdkDecor |= GDK_DECOR_MINIMIZE;
576 }
577 if ((style & wxMAXIMIZE_BOX) != 0)
578 {
579 m_gdkFunc |= GDK_FUNC_MAXIMIZE;
580 m_gdkDecor |= GDK_DECOR_MAXIMIZE;
581 }
582 if ((style & wxRESIZE_BORDER) != 0)
583 {
584 m_gdkFunc |= GDK_FUNC_RESIZE;
585 m_gdkDecor |= GDK_DECOR_RESIZEH;
586 }
587 }
588
7d9f12f3
VS
589 return TRUE;
590}
591
592wxTopLevelWindowGTK::~wxTopLevelWindowGTK()
593{
5152b0e5
JS
594 if (m_grabbed)
595 {
83afe211 596 wxASSERT_MSG( FALSE, _T("Window still grabbed"));
5152b0e5
JS
597 RemoveGrab();
598 }
1cbee0b4 599
7d9f12f3 600 m_isBeingDeleted = TRUE;
6aeb6f2a 601
710968c3
VZ
602 // it may also be GtkScrolledWindow in the case of an MDI child
603 if (GTK_IS_WINDOW(m_widget))
604 {
605 gtk_window_set_focus( GTK_WINDOW(m_widget), NULL );
606 }
06fda9e8
RR
607
608 if (g_activeFrame == this)
609 g_activeFrame = NULL;
610 if (g_lastActiveFrame == this)
611 g_lastActiveFrame = NULL;
7d9f12f3
VS
612}
613
8a9650ea 614
8a9650ea 615
7d9f12f3
VS
616bool wxTopLevelWindowGTK::ShowFullScreen(bool show, long style )
617{
618 if (show == m_fsIsShowing) return FALSE; // return what?
619
620 m_fsIsShowing = show;
621
8166ab43 622 GdkWindow *window = m_widget->window;
1542ea39 623 wxX11FullScreenMethod method =
8166ab43
VS
624 wxGetFullScreenMethodX11((WXDisplay*)GDK_DISPLAY(),
625 (WXWindow)GDK_ROOT_WINDOW());
1542ea39 626
7d9f12f3
VS
627 if (show)
628 {
7d9f12f3
VS
629 m_fsSaveFlag = style;
630 GetPosition( &m_fsSaveFrame.x, &m_fsSaveFrame.y );
631 GetSize( &m_fsSaveFrame.width, &m_fsSaveFrame.height );
632
8a9650ea
RR
633 int screen_width,screen_height;
634 wxDisplaySize( &screen_width, &screen_height );
1cbee0b4 635
8a9650ea
RR
636 gint client_x, client_y, root_x, root_y;
637 gint width, height;
7d9f12f3 638
1cff04de 639 if (method != wxX11_FS_WMSPEC)
8166ab43
VS
640 {
641 // don't do it always, Metacity hates it
642 m_fsSaveGdkFunc = m_gdkFunc;
643 m_fsSaveGdkDecor = m_gdkDecor;
644 m_gdkFunc = m_gdkDecor = 0;
645 gdk_window_set_decorations(window, (GdkWMDecoration)0);
646 gdk_window_set_functions(window, (GdkWMFunction)0);
647 }
1542ea39 648
8a9650ea
RR
649 gdk_window_get_origin (m_widget->window, &root_x, &root_y);
650 gdk_window_get_geometry (m_widget->window, &client_x, &client_y,
651 &width, &height, NULL);
1cbee0b4 652
8a9650ea
RR
653 gdk_window_move_resize (m_widget->window, -client_x, -client_y,
654 screen_width + 1, screen_height + 1);
8166ab43
VS
655
656 wxSetFullScreenStateX11((WXDisplay*)GDK_DISPLAY(),
657 (WXWindow)GDK_ROOT_WINDOW(),
658 (WXWindow)GDK_WINDOW_XWINDOW(window),
659 show, &m_fsSaveFrame, method);
7d9f12f3
VS
660 }
661 else
662 {
1cff04de 663 if (method != wxX11_FS_WMSPEC)
8166ab43
VS
664 {
665 // don't do it always, Metacity hates it
666 m_gdkFunc = m_fsSaveGdkFunc;
667 m_gdkDecor = m_fsSaveGdkDecor;
668 gdk_window_set_decorations(window, (GdkWMDecoration)m_gdkDecor);
669 gdk_window_set_functions(window, (GdkWMFunction)m_gdkFunc);
670 }
1542ea39 671
8166ab43
VS
672 wxSetFullScreenStateX11((WXDisplay*)GDK_DISPLAY(),
673 (WXWindow)GDK_ROOT_WINDOW(),
674 (WXWindow)GDK_WINDOW_XWINDOW(window),
675 show, &m_fsSaveFrame, method);
1542ea39 676
8166ab43
VS
677 SetSize(m_fsSaveFrame.x, m_fsSaveFrame.y,
678 m_fsSaveFrame.width, m_fsSaveFrame.height);
7d9f12f3
VS
679 }
680
8166ab43 681
7d9f12f3
VS
682 return TRUE;
683}
684
685// ----------------------------------------------------------------------------
686// overridden wxWindow methods
687// ----------------------------------------------------------------------------
688
689bool wxTopLevelWindowGTK::Show( bool show )
690{
82b978d7 691 wxASSERT_MSG( (m_widget != NULL), wxT("invalid frame") );
7d9f12f3
VS
692
693 if (show && !m_sizeSet)
694 {
695 /* by calling GtkOnSize here, we don't have to call
696 either after showing the frame, which would entail
697 much ugly flicker or from within the size_allocate
698 handler, because GTK 1.1.X forbids that. */
699
700 GtkOnSize( m_x, m_y, m_width, m_height );
701 }
702
703 return wxWindow::Show( show );
704}
705
706void wxTopLevelWindowGTK::DoMoveWindow(int WXUNUSED(x), int WXUNUSED(y), int WXUNUSED(width), int WXUNUSED(height) )
707{
708 wxFAIL_MSG( wxT("DoMoveWindow called for wxTopLevelWindowGTK") );
709}
710
711void wxTopLevelWindowGTK::DoSetSize( int x, int y, int width, int height, int sizeFlags )
712{
82b978d7
RD
713 wxASSERT_MSG( (m_widget != NULL), wxT("invalid frame") );
714
e1f14d22 715 // this shouldn't happen: wxFrame, wxMDIParentFrame and wxMDIChildFrame have m_wxwindow
7d9f12f3
VS
716 wxASSERT_MSG( (m_wxwindow != NULL), wxT("invalid frame") );
717
e1f14d22 718 // avoid recursions
7d9f12f3
VS
719 if (m_resizing)
720 return;
721 m_resizing = TRUE;
722
723 int old_x = m_x;
724 int old_y = m_y;
725
726 int old_width = m_width;
727 int old_height = m_height;
728
729 if ((sizeFlags & wxSIZE_ALLOW_MINUS_ONE) == 0)
730 {
731 if (x != -1) m_x = x;
732 if (y != -1) m_y = y;
7d9f12f3
VS
733 }
734 else
735 {
736 m_x = x;
737 m_y = y;
7d9f12f3 738 }
d44c23ce
RR
739 if (width != -1) m_width = width;
740 if (height != -1) m_height = height;
7d9f12f3
VS
741
742/*
743 if ((sizeFlags & wxSIZE_AUTO_WIDTH) == wxSIZE_AUTO_WIDTH)
744 {
745 if (width == -1) m_width = 80;
746 }
747
748 if ((sizeFlags & wxSIZE_AUTO_HEIGHT) == wxSIZE_AUTO_HEIGHT)
749 {
750 if (height == -1) m_height = 26;
751 }
752*/
753
e7dda1ff
VS
754 int minWidth = GetMinWidth(),
755 minHeight = GetMinHeight(),
756 maxWidth = GetMaxWidth(),
757 maxHeight = GetMaxHeight();
758
62be94e1
RR
759#ifdef __WXGPE__
760 // GPE's window manager doesn't like size hints
761 // at all, esp. when the user has to use the
762 // virtual keyboard.
763 minWidth = -1;
764 minHeight = -1;
765 maxWidth = -1;
766 maxHeight = -1;
767#endif
ca06ee0d 768
e7dda1ff
VS
769 if ((minWidth != -1) && (m_width < minWidth)) m_width = minWidth;
770 if ((minHeight != -1) && (m_height < minHeight)) m_height = minHeight;
771 if ((maxWidth != -1) && (m_width > maxWidth)) m_width = maxWidth;
772 if ((maxHeight != -1) && (m_height > maxHeight)) m_height = maxHeight;
7d9f12f3
VS
773
774 if ((m_x != -1) || (m_y != -1))
775 {
776 if ((m_x != old_x) || (m_y != old_y))
777 {
778 gtk_widget_set_uposition( m_widget, m_x, m_y );
779 }
780 }
781
782 if ((m_width != old_width) || (m_height != old_height))
783 {
e1f14d22
RR
784 if (m_widget->window)
785 gdk_window_resize( m_widget->window, m_width, m_height );
786 else
787 gtk_window_set_default_size( GTK_WINDOW(m_widget), m_width, m_height );
7d9f12f3
VS
788
789 /* we set the size in GtkOnSize, i.e. mostly the actual resizing is
790 done either directly before the frame is shown or in idle time
791 so that different calls to SetSize() don't lead to flicker. */
792 m_sizeSet = FALSE;
793 }
794
795 m_resizing = FALSE;
796}
797
798void wxTopLevelWindowGTK::DoGetClientSize( int *width, int *height ) const
799{
82b978d7
RD
800 wxASSERT_MSG( (m_widget != NULL), wxT("invalid frame") );
801
7d9f12f3
VS
802 wxWindow::DoGetClientSize( width, height );
803 if (height)
804 {
e1f14d22 805 // mini edge
7d9f12f3
VS
806 *height -= m_miniEdge*2 + m_miniTitle;
807 }
808 if (width)
809 {
810 *width -= m_miniEdge*2;
811 }
812}
813
814void wxTopLevelWindowGTK::DoSetClientSize( int width, int height )
815{
82b978d7 816 wxASSERT_MSG( (m_widget != NULL), wxT("invalid frame") );
7d9f12f3 817
82c9f85c 818 DoSetSize(-1, -1,
7d9f12f3
VS
819 width + m_miniEdge*2, height + m_miniEdge*2 + m_miniTitle, 0);
820}
821
822void wxTopLevelWindowGTK::GtkOnSize( int WXUNUSED(x), int WXUNUSED(y),
82c9f85c 823 int width, int height )
7d9f12f3
VS
824{
825 // due to a bug in gtk, x,y are always 0
826 // m_x = x;
827 // m_y = y;
828
e1f14d22 829 // avoid recursions
7d9f12f3
VS
830 if (m_resizing) return;
831 m_resizing = TRUE;
832
833 if ( m_wxwindow == NULL ) return;
834
835 m_width = width;
836 m_height = height;
837
0d53fc34 838 /* wxMDIChildFrame derives from wxFrame but it _is_ a wxWindow as it uses
7d9f12f3 839 wxWindow::Create to create it's GTK equivalent. m_mainWidget is only
0d53fc34 840 set in wxFrame::Create so it is used to check what kind of frame we
7d9f12f3
VS
841 have here. if m_mainWidget is NULL it is a wxMDIChildFrame and so we
842 skip the part which handles m_frameMenuBar, m_frameToolBar and (most
843 importantly) m_mainWidget */
844
e7dda1ff
VS
845 int minWidth = GetMinWidth(),
846 minHeight = GetMinHeight(),
847 maxWidth = GetMaxWidth(),
848 maxHeight = GetMaxHeight();
849
62be94e1
RR
850#ifdef __WXGPE__
851 // GPE's window manager doesn't like size hints
852 // at all, esp. when the user has to use the
853 // virtual keyboard.
854 minWidth = -1;
855 minHeight = -1;
856 maxWidth = -1;
857 maxHeight = -1;
858#endif
ca06ee0d 859
e7dda1ff
VS
860 if ((minWidth != -1) && (m_width < minWidth)) m_width = minWidth;
861 if ((minHeight != -1) && (m_height < minHeight)) m_height = minHeight;
862 if ((maxWidth != -1) && (m_width > maxWidth)) m_width = maxWidth;
863 if ((maxHeight != -1) && (m_height > maxHeight)) m_height = maxHeight;
7d9f12f3
VS
864
865 if (m_mainWidget)
866 {
e1f14d22 867 // set size hints
801225c1
RL
868 gint flag = 0; // GDK_HINT_POS;
869 GdkGeometry geom;
870
e7dda1ff
VS
871 if ((minWidth != -1) || (minHeight != -1)) flag |= GDK_HINT_MIN_SIZE;
872 if ((maxWidth != -1) || (maxHeight != -1)) flag |= GDK_HINT_MAX_SIZE;
801225c1 873
e7dda1ff
VS
874 geom.min_width = minWidth;
875 geom.min_height = minHeight;
801225c1
RL
876
877 // Because of the way we set GDK_HINT_MAX_SIZE above, if either of
878 // maxHeight or maxWidth is set, we must set them both, else the
879 // remaining -1 will be taken literally.
880
881 // I'm certain this also happens elsewhere, and is the probable
882 // cause of other such things as:
883 // Gtk-WARNING **: gtk_widget_size_allocate():
884 // attempt to allocate widget with width 65535 and height 600
885 // but I don't have time to track them all now..
1cbee0b4 886 //
801225c1
RL
887 // Really we need to encapulate all this height/width business and
888 // stop any old method from ripping at the members directly and
889 // scattering -1's without regard for who might resolve them later.
890
891 geom.max_width = ( maxHeight == -1 ) ? maxWidth
892 : ( maxWidth == -1 ) ? wxGetDisplaySize().GetWidth()
893 : maxWidth ;
894
895 geom.max_height = ( maxWidth == -1 ) ? maxHeight // ( == -1 here )
896 : ( maxHeight == -1 ) ? wxGetDisplaySize().GetHeight()
897 : maxHeight ;
898
7d9f12f3
VS
899 gtk_window_set_geometry_hints( GTK_WINDOW(m_widget),
900 (GtkWidget*) NULL,
901 &geom,
902 (GdkWindowHints) flag );
903
904 /* I revert back to wxGTK's original behaviour. m_mainWidget holds the
905 * menubar, the toolbar and the client area, which is represented by
906 * m_wxwindow.
907 * this hurts in the eye, but I don't want to call SetSize()
908 * because I don't want to call any non-native functions here. */
909
910 int client_x = m_miniEdge;
911 int client_y = m_miniEdge + m_miniTitle;
912 int client_w = m_width - 2*m_miniEdge;
913 int client_h = m_height - 2*m_miniEdge - m_miniTitle;
801225c1 914
7d9f12f3
VS
915 gtk_pizza_set_size( GTK_PIZZA(m_mainWidget),
916 m_wxwindow,
917 client_x, client_y, client_w, client_h );
918 }
919 else
920 {
e1f14d22
RR
921 // If there is no m_mainWidget between m_widget and m_wxwindow there
922 // is no need to set the size or position of m_wxwindow.
7d9f12f3
VS
923 }
924
925 m_sizeSet = TRUE;
926
927 // send size event to frame
928 wxSizeEvent event( wxSize(m_width,m_height), GetId() );
929 event.SetEventObject( this );
930 GetEventHandler()->ProcessEvent( event );
931
932 m_resizing = FALSE;
933}
934
935void wxTopLevelWindowGTK::OnInternalIdle()
936{
937 if (!m_sizeSet && GTK_WIDGET_REALIZED(m_wxwindow))
938 {
939 GtkOnSize( m_x, m_y, m_width, m_height );
940
941 // we'll come back later
942 if (g_isIdle)
943 wxapp_install_idle_handler();
944 return;
945 }
946
6aeb6f2a
VZ
947 // set the focus if not done yet and if we can already do it
948 if ( GTK_WIDGET_REALIZED(m_wxwindow) )
949 {
cc06fe74
MB
950 if ( g_delayedFocus &&
951 wxGetTopLevelParent((wxWindow*)g_delayedFocus) == this )
6aeb6f2a 952 {
2b5f62a0
VZ
953 wxLogTrace(_T("focus"),
954 _T("Setting focus from wxTLW::OnIdle() to %s(%s)"),
955 g_delayedFocus->GetClassInfo()->GetClassName(),
956 g_delayedFocus->GetLabel().c_str());
957
6aeb6f2a
VZ
958 g_delayedFocus->SetFocus();
959 g_delayedFocus = NULL;
960 }
961 }
962
7d9f12f3 963 wxWindow::OnInternalIdle();
06fda9e8
RR
964
965 // Synthetize activate events.
966 if ( g_sendActivateEvent != -1 )
967 {
968 bool activate = g_sendActivateEvent != 0;
969
970 // do it only once
971 g_sendActivateEvent = -1;
972
973 wxTheApp->SetActive(activate, (wxWindow *)g_lastActiveFrame);
974 }
7d9f12f3
VS
975}
976
7d9f12f3
VS
977// ----------------------------------------------------------------------------
978// frame title/icon
979// ----------------------------------------------------------------------------
980
981void wxTopLevelWindowGTK::SetTitle( const wxString &title )
982{
82b978d7
RD
983 wxASSERT_MSG( (m_widget != NULL), wxT("invalid frame") );
984
7d9f12f3 985 m_title = title;
fab591c5 986 gtk_window_set_title( GTK_WINDOW(m_widget), wxGTK_CONV( title ) );
7d9f12f3
VS
987}
988
f618020a
MB
989void wxTopLevelWindowGTK::SetIcon( const wxIcon &icon )
990{
991 SetIcons( wxIconBundle( icon ) );
992}
993
994void wxTopLevelWindowGTK::SetIcons( const wxIconBundle &icons )
995{
82b978d7 996 wxASSERT_MSG( (m_widget != NULL), wxT("invalid frame") );
f618020a
MB
997
998 wxTopLevelWindowBase::SetIcons( icons );
999
87e53e2a
VS
1000#ifdef __WXGTK20__
1001 GList *list = NULL;
1002 size_t max = icons.m_icons.GetCount();
1003
1004 for (size_t i = 0; i < max; i++)
52d6235d 1005 {
87e53e2a
VS
1006 if (icons.m_icons[i].Ok())
1007 {
1008 list = g_list_prepend(list, icons.m_icons[i].GetPixbuf());
1009 }
1010 }
1011 gtk_window_set_icon_list(GTK_WINDOW(m_widget), list);
1012 g_list_free(list);
1013
1014#else // !__WXGTK20__
1015 GdkWindow* window = m_widget->window;
1016 if (!window)
1017 return;
1018
1019 wxIcon icon = icons.GetIcon(-1);
1020 if (icon.Ok())
1021 {
1022 wxMask *mask = icon.GetMask();
1023 GdkBitmap *bm = (GdkBitmap *) NULL;
1024 if (mask) bm = mask->GetBitmap();
1025
1026 gdk_window_set_icon( m_widget->window, (GdkWindow *) NULL, icon.GetPixmap(), bm );
52d6235d 1027 }
87e53e2a
VS
1028
1029 wxSetIconsX11( (WXDisplay*)GDK_WINDOW_XDISPLAY( window ),
1030 (WXWindow)GDK_WINDOW_XWINDOW( window ), icons );
1031#endif // !__WXGTK20__
f618020a
MB
1032}
1033
7d9f12f3
VS
1034// ----------------------------------------------------------------------------
1035// frame state: maximized/iconized/normal
1036// ----------------------------------------------------------------------------
1037
8805e155 1038void wxTopLevelWindowGTK::Maximize(bool maximize)
7d9f12f3 1039{
8805e155
RR
1040#ifdef __WXGTK20__
1041 if (maximize)
1042 gtk_window_maximize( GTK_WINDOW( m_widget ) );
1043 else
1044 gtk_window_unmaximize( GTK_WINDOW( m_widget ) );
1045#else
7d9f12f3 1046 wxFAIL_MSG( _T("not implemented") );
8805e155 1047#endif
7d9f12f3
VS
1048}
1049
1050bool wxTopLevelWindowGTK::IsMaximized() const
1051{
d8e1fe80
VS
1052#ifdef __WXGTK20__
1053 if(!m_widget->window)
1054 return false;
1055
1056 return gdk_window_get_state(m_widget->window) & GDK_WINDOW_STATE_MAXIMIZED;
1057#else
7d9f12f3
VS
1058 // wxFAIL_MSG( _T("not implemented") );
1059
1060 // This is an approximation
1061 return FALSE;
d8e1fe80 1062#endif
7d9f12f3
VS
1063}
1064
1065void wxTopLevelWindowGTK::Restore()
1066{
387fd89d 1067#ifdef __WXGTK20__
8805e155
RR
1068 // "Present" seems similar enough to "restore"
1069 gtk_window_present( GTK_WINDOW( m_widget ) );
1070#else
7d9f12f3 1071 wxFAIL_MSG( _T("not implemented") );
8805e155 1072#endif
7d9f12f3
VS
1073}
1074
1075void wxTopLevelWindowGTK::Iconize( bool iconize )
1076{
8805e155
RR
1077#ifdef __WXGTK20__
1078 if (iconize)
1079 gtk_window_iconify( GTK_WINDOW( m_widget ) );
1080 else
1081 gtk_window_deiconify( GTK_WINDOW( m_widget ) );
1082#else
7d9f12f3
VS
1083 if (iconize)
1084 {
1085 GdkWindow *window = m_widget->window;
1086
1087 // you should do it later, for example from OnCreate() handler
1088 wxCHECK_RET( window, _T("frame not created yet - can't iconize") );
1089
1090 XIconifyWindow( GDK_WINDOW_XDISPLAY( window ),
1091 GDK_WINDOW_XWINDOW( window ),
1092 DefaultScreen( GDK_DISPLAY() ) );
1093 }
8805e155 1094#endif
7d9f12f3
VS
1095}
1096
1097bool wxTopLevelWindowGTK::IsIconized() const
1098{
1099 return m_isIconized;
1100}
1101
1102void wxTopLevelWindowGTK::SetIconizeState(bool iconize)
1103{
1104 if ( iconize != m_isIconized )
1105 {
1106 m_isIconized = iconize;
1107 (void)SendIconizeEvent(iconize);
1108 }
1109}
1110
5152b0e5
JS
1111void wxTopLevelWindowGTK::AddGrab()
1112{
1113 if (!m_grabbed)
1114 {
1115 m_grabbed = TRUE;
1116 gtk_grab_add( m_widget );
1117 gtk_main();
1118 gtk_grab_remove( m_widget );
1119 }
1120}
1121
1122void wxTopLevelWindowGTK::RemoveGrab()
1123{
1124 if (m_grabbed)
1125 {
1126 gtk_main_quit();
1127 m_grabbed = FALSE;
1128 }
1129}
801225c1 1130
1542ea39
RD
1131
1132// helper
1133static bool do_shape_combine_region(GdkWindow* window, const wxRegion& region)
1134{
1135 if (window)
1136 {
1137 if (region.IsEmpty())
1138 {
1139 gdk_window_shape_combine_mask(window, NULL, 0, 0);
1140 }
1141 else
1142 {
1143#ifdef __WXGTK20__
1144 gdk_window_shape_combine_region(window, region.GetRegion(), 0, 0);
1145#else
1146 wxBitmap bmp = region.ConvertToBitmap();
819451b6 1147 bmp.SetMask(new wxMask(bmp, *wxBLACK));
1542ea39
RD
1148 GdkBitmap* mask = bmp.GetMask()->GetBitmap();
1149 gdk_window_shape_combine_mask(window, mask, 0, 0);
1150#endif
1151 return TRUE;
1152 }
1153 }
1154 return FALSE;
1155}
1156
1157
1158bool wxTopLevelWindowGTK::SetShape(const wxRegion& region)
1159{
6a7e6411
RD
1160 wxCHECK_MSG( HasFlag(wxFRAME_SHAPED), FALSE,
1161 _T("Shaped windows must be created with the wxFRAME_SHAPED style."));
1162
1542ea39
RD
1163 GdkWindow *window = NULL;
1164 if (m_wxwindow)
1165 {
1166 window = GTK_PIZZA(m_wxwindow)->bin_window;
1167 do_shape_combine_region(window, region);
1168 }
1169 window = m_widget->window;
1170 return do_shape_combine_region(window, region);
1171}
1172
6b30a44e 1173bool wxTopLevelWindowGTK::IsActive()
35ff90a0 1174{
06fda9e8 1175 return (this == (wxTopLevelWindowGTK*)g_activeFrame);
35ff90a0
RR
1176}
1177