]> git.saurik.com Git - wxWidgets.git/blame - src/gtk/toplevel.cpp
No change
[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
7// Licence: wxWindows licence
8/////////////////////////////////////////////////////////////////////////////
9
10// ============================================================================
11// declarations
12// ============================================================================
13
14// ----------------------------------------------------------------------------
15// headers
16// ----------------------------------------------------------------------------
17
18#ifdef __GNUG__
19 #pragma implementation "toplevel.h"
20#endif
21
22#ifdef __VMS
23#define XIconifyWindow XICONIFYWINDOW
24#endif
25
26#include "wx/defs.h"
27
28#include "wx/dialog.h"
29#include "wx/control.h"
30#include "wx/app.h"
31#include "wx/dcclient.h"
32
33#include <glib.h>
34#include <gdk/gdk.h>
35#include <gtk/gtk.h>
36#include <gdk/gdkkeysyms.h>
37#include <gdk/gdkx.h>
38
39#include "wx/gtk/win_gtk.h"
40
f618020a
MB
41#include "wx/unix/utilsx11.h"
42
7d9f12f3
VS
43// ----------------------------------------------------------------------------
44// idle system
45// ----------------------------------------------------------------------------
46
47extern void wxapp_install_idle_handler();
48extern bool g_isIdle;
49extern int g_openDialogs;
50
51// ----------------------------------------------------------------------------
52// event tables
53// ----------------------------------------------------------------------------
54
7d9f12f3
VS
55// ----------------------------------------------------------------------------
56// data
57// ----------------------------------------------------------------------------
58
59extern wxList wxPendingDelete;
60
61// ----------------------------------------------------------------------------
62// debug
63// ----------------------------------------------------------------------------
64
65#ifdef __WXDEBUG__
66
67extern void debug_focus_in( GtkWidget* widget, const wxChar* name, const wxChar *window );
68
69#endif
70
71// ============================================================================
72// implementation
73// ============================================================================
74
75// ----------------------------------------------------------------------------
76// GTK callbacks
77// ----------------------------------------------------------------------------
78
79//-----------------------------------------------------------------------------
80// "focus" from m_window
81//-----------------------------------------------------------------------------
82
83static gint gtk_frame_focus_callback( GtkWidget *widget, GtkDirectionType WXUNUSED(d), wxWindow *WXUNUSED(win) )
84{
85 if (g_isIdle)
86 wxapp_install_idle_handler();
87
88 // This disables GTK's tab traversal
89 gtk_signal_emit_stop_by_name( GTK_OBJECT(widget), "focus" );
90 return TRUE;
91}
92
93//-----------------------------------------------------------------------------
94// "size_allocate"
95//-----------------------------------------------------------------------------
96
97static void gtk_frame_size_callback( GtkWidget *WXUNUSED(widget), GtkAllocation* alloc, wxTopLevelWindowGTK *win )
98{
99 if (g_isIdle)
100 wxapp_install_idle_handler();
101
102 if (!win->m_hasVMT)
103 return;
104
105 if ((win->m_width != alloc->width) || (win->m_height != alloc->height))
106 {
107/*
108 wxPrintf( "OnSize from " );
109 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
110 wxPrintf( win->GetClassInfo()->GetClassName() );
111 wxPrintf( " %d %d %d %d\n", (int)alloc->x,
112 (int)alloc->y,
113 (int)alloc->width,
114 (int)alloc->height );
115*/
116
117 win->m_width = alloc->width;
118 win->m_height = alloc->height;
119 win->m_queuedFullRedraw = TRUE;
120 win->GtkUpdateSize();
121 }
122}
123
124//-----------------------------------------------------------------------------
125// "delete_event"
126//-----------------------------------------------------------------------------
127
128static gint gtk_frame_delete_callback( GtkWidget *WXUNUSED(widget), GdkEvent *WXUNUSED(event), wxTopLevelWindowGTK *win )
129{
130 if (g_isIdle)
131 wxapp_install_idle_handler();
132
133 if (win->IsEnabled() &&
f819b4a3 134 (g_openDialogs == 0 || (win->GetExtraStyle() & wxTOPLEVEL_EX_DIALOG)))
7d9f12f3
VS
135 win->Close();
136
137 return TRUE;
138}
139
140
141//-----------------------------------------------------------------------------
142// "configure_event"
143//-----------------------------------------------------------------------------
144
145static gint
7d9f12f3 146gtk_frame_configure_callback( GtkWidget *WXUNUSED(widget), GdkEventConfigure *WXUNUSED(event), wxTopLevelWindowGTK *win )
7d9f12f3
VS
147{
148 if (g_isIdle)
149 wxapp_install_idle_handler();
150
48f72114 151 if (!win->m_hasVMT || !win->IsShown())
7d9f12f3
VS
152 return FALSE;
153
7d9f12f3
VS
154 int x = 0;
155 int y = 0;
156 gdk_window_get_root_origin( win->m_widget->window, &x, &y );
157 win->m_x = x;
158 win->m_y = y;
7d9f12f3
VS
159
160 wxMoveEvent mevent( wxPoint(win->m_x,win->m_y), win->GetId() );
161 mevent.SetEventObject( win );
162 win->GetEventHandler()->ProcessEvent( mevent );
163
164 return FALSE;
165}
166
167//-----------------------------------------------------------------------------
168// "realize" from m_widget
169//-----------------------------------------------------------------------------
170
e1f14d22
RR
171// we cannot MWM hints and icons before the widget has been realized,
172// so we do this directly after realization
7d9f12f3
VS
173
174static void
175gtk_frame_realized_callback( GtkWidget * WXUNUSED(widget), wxTopLevelWindowGTK *win )
176{
177 if (g_isIdle)
178 wxapp_install_idle_handler();
179
e1f14d22
RR
180 // All this is for Motif Window Manager "hints" and is supposed to be
181 // recognized by other WM as well. Not tested.
82c9f85c 182 gdk_window_set_decorations(win->m_widget->window,
f819b4a3 183 (GdkWMDecoration)win->m_gdkDecor);
82c9f85c 184 gdk_window_set_functions(win->m_widget->window,
f819b4a3 185 (GdkWMFunction)win->m_gdkFunc);
7d9f12f3 186
e1f14d22 187 // GTK's shrinking/growing policy
f819b4a3 188 if ((win->m_gdkFunc & GDK_FUNC_RESIZE) == 0)
7d9f12f3
VS
189 gtk_window_set_policy(GTK_WINDOW(win->m_widget), 0, 0, 1);
190 else
191 gtk_window_set_policy(GTK_WINDOW(win->m_widget), 1, 1, 1);
192
e1f14d22 193 // reset the icon
7efaed4d
MB
194 wxIconBundle iconsOld = win->GetIcons();
195 wxIcon tmp = iconsOld.GetIcon( -1 ); // operator != is not-const
196 if ( tmp != wxNullIcon )
7d9f12f3 197 {
7efaed4d 198 // wxIconBundle icon( iconOld );
7d9f12f3 199 win->SetIcon( wxNullIcon );
7efaed4d 200 win->SetIcons( iconsOld );
7d9f12f3
VS
201 }
202
e1f14d22
RR
203 // we set the focus to the child that accepts the focus. this
204 // doesn't really have to be done in "realize" but why not?
7d9f12f3
VS
205 wxWindowList::Node *node = win->GetChildren().GetFirst();
206 while (node)
207 {
208 wxWindow *child = node->GetData();
209 if (child->AcceptsFocus())
210 {
211 child->SetFocus();
212 break;
213 }
214
215 node = node->GetNext();
216 }
217}
218
219//-----------------------------------------------------------------------------
220// "map_event" from m_widget
221//-----------------------------------------------------------------------------
222
223static void
224gtk_frame_map_callback( GtkWidget * WXUNUSED(widget),
225 GdkEvent * WXUNUSED(event),
226 wxTopLevelWindow *win )
227{
228 win->SetIconizeState(FALSE);
229}
230
231//-----------------------------------------------------------------------------
232// "unmap_event" from m_widget
233//-----------------------------------------------------------------------------
234
235static void
236gtk_frame_unmap_callback( GtkWidget * WXUNUSED(widget),
237 GdkEvent * WXUNUSED(event),
238 wxTopLevelWindow *win )
239{
240 win->SetIconizeState(TRUE);
241}
242
243//-----------------------------------------------------------------------------
244// "expose_event" of m_client
245//-----------------------------------------------------------------------------
246
247static int gtk_window_expose_callback( GtkWidget *widget, GdkEventExpose *gdk_event, wxWindow *win )
248{
249 GtkPizza *pizza = GTK_PIZZA(widget);
250
90350682
VZ
251 gtk_paint_flat_box (win->m_widget->style,
252 pizza->bin_window, GTK_STATE_NORMAL,
253 GTK_SHADOW_NONE,
254 &gdk_event->area,
255 win->m_widget,
256 (char *)"base",
257 0, 0, -1, -1);
7d9f12f3
VS
258
259 return TRUE;
260}
261
262//-----------------------------------------------------------------------------
263// "draw" of m_client
264//-----------------------------------------------------------------------------
265
52d6235d 266#ifndef __WXGTK20__
7d9f12f3
VS
267
268static void gtk_window_draw_callback( GtkWidget *widget, GdkRectangle *rect, wxWindow *win )
269{
270 GtkPizza *pizza = GTK_PIZZA(widget);
271
90350682
VZ
272 gtk_paint_flat_box (win->m_widget->style,
273 pizza->bin_window, GTK_STATE_NORMAL,
274 GTK_SHADOW_NONE,
275 rect,
276 win->m_widget,
277 (char *)"base",
278 0, 0, -1, -1);
7d9f12f3
VS
279}
280
52d6235d
VZ
281#endif // GTK+ 1.x
282
7d9f12f3
VS
283// ----------------------------------------------------------------------------
284// wxTopLevelWindowGTK itself
285// ----------------------------------------------------------------------------
286
287//-----------------------------------------------------------------------------
288// InsertChild for wxTopLevelWindowGTK
289//-----------------------------------------------------------------------------
290
291/* Callback for wxTopLevelWindowGTK. This very strange beast has to be used because
292 * C++ has no virtual methods in a constructor. We have to emulate a
293 * virtual function here as wxWindows requires different ways to insert
294 * a child in container classes. */
295
296static void wxInsertChildInTopLevelWindow( wxTopLevelWindowGTK* parent, wxWindow* child )
297{
298 wxASSERT( GTK_IS_WIDGET(child->m_widget) );
299
300 if (!parent->m_insertInClientArea)
301 {
e1f14d22 302 // these are outside the client area
7d9f12f3
VS
303 wxTopLevelWindowGTK* frame = (wxTopLevelWindowGTK*) parent;
304 gtk_pizza_put( GTK_PIZZA(frame->m_mainWidget),
305 GTK_WIDGET(child->m_widget),
306 child->m_x,
307 child->m_y,
308 child->m_width,
309 child->m_height );
310 }
311 else
312 {
e1f14d22 313 // these are inside the client area
7d9f12f3
VS
314 gtk_pizza_put( GTK_PIZZA(parent->m_wxwindow),
315 GTK_WIDGET(child->m_widget),
e4b7b2b0
VS
316 child->m_x,
317 child->m_y,
7d9f12f3
VS
318 child->m_width,
319 child->m_height );
320 }
321
e1f14d22 322 // resize on OnInternalIdle
7d9f12f3
VS
323 parent->GtkUpdateSize();
324}
325
326// ----------------------------------------------------------------------------
327// wxTopLevelWindowGTK creation
328// ----------------------------------------------------------------------------
329
330void wxTopLevelWindowGTK::Init()
331{
332 m_sizeSet = FALSE;
333 m_miniEdge = 0;
334 m_miniTitle = 0;
335 m_mainWidget = (GtkWidget*) NULL;
336 m_insertInClientArea = TRUE;
337 m_isFrame = TRUE;
338 m_isIconized = FALSE;
339 m_fsIsShowing = FALSE;
340 m_themeEnabled = TRUE;
f819b4a3 341 m_gdkDecor = m_gdkFunc = 0;
7d9f12f3
VS
342}
343
344bool wxTopLevelWindowGTK::Create( wxWindow *parent,
f819b4a3
VS
345 wxWindowID id,
346 const wxString& title,
347 const wxPoint& pos,
348 const wxSize& sizeOrig,
349 long style,
350 const wxString &name )
7d9f12f3
VS
351{
352 // always create a frame of some reasonable, even if arbitrary, size (at
353 // least for MSW compatibility)
354 wxSize size = sizeOrig;
355 if ( size.x == -1 || size.y == -1 )
356 {
357 wxSize sizeDpy = wxGetDisplaySize();
358 if ( size.x == -1 )
359 size.x = sizeDpy.x / 3;
360 if ( size.y == -1 )
361 size.y = sizeDpy.y / 5;
362 }
363
364 wxTopLevelWindows.Append( this );
365
366 m_needParent = FALSE;
2c990ec0 367
7d9f12f3
VS
368 if (!PreCreation( parent, pos, size ) ||
369 !CreateBase( parent, id, pos, size, style, wxDefaultValidator, name ))
370 {
371 wxFAIL_MSG( wxT("wxTopLevelWindowGTK creation failed") );
372 return FALSE;
373 }
374
375 m_title = title;
376
377 m_insertCallback = (wxInsertChildFunction) wxInsertChildInTopLevelWindow;
378
379 GtkWindowType win_type = GTK_WINDOW_TOPLEVEL;
380
381 if (style & wxFRAME_TOOL_WINDOW)
382 win_type = GTK_WINDOW_POPUP;
82c9f85c 383
f819b4a3 384 if (GetExtraStyle() & wxTOPLEVEL_EX_DIALOG)
9e691f46
VZ
385 {
386 // there is no more GTK_WINDOW_DIALOG in 2.0
387#ifdef __WXGTK20__
388 win_type = GTK_WINDOW_TOPLEVEL;
389#else
7d9f12f3 390 win_type = GTK_WINDOW_DIALOG;
9e691f46
VZ
391#endif
392 }
7d9f12f3
VS
393
394 m_widget = gtk_window_new( win_type );
395
7cd95599 396 if (m_parent && (GTK_IS_WINDOW(m_parent->m_widget)) &&
2c990ec0 397 (GetExtraStyle() & wxTOPLEVEL_EX_DIALOG))
7cd95599 398 {
7d9f12f3 399 gtk_window_set_transient_for( GTK_WINDOW(m_widget), GTK_WINDOW(m_parent->m_widget) );
7cd95599 400 }
7d9f12f3
VS
401
402 if (!name.IsEmpty())
403 gtk_window_set_wmclass( GTK_WINDOW(m_widget), name.mb_str(), name.mb_str() );
404
405#ifdef __WXDEBUG__
406 debug_focus_in( m_widget, wxT("wxTopLevelWindowGTK::m_widget"), name );
407#endif
408
409 gtk_window_set_title( GTK_WINDOW(m_widget), title.mbc_str() );
410 GTK_WIDGET_UNSET_FLAGS( m_widget, GTK_CAN_FOCUS );
411
412 gtk_signal_connect( GTK_OBJECT(m_widget), "delete_event",
413 GTK_SIGNAL_FUNC(gtk_frame_delete_callback), (gpointer)this );
414
e1f14d22 415 // m_mainWidget holds the toolbar, the menubar and the client area
7d9f12f3
VS
416 m_mainWidget = gtk_pizza_new();
417 gtk_widget_show( m_mainWidget );
418 GTK_WIDGET_UNSET_FLAGS( m_mainWidget, GTK_CAN_FOCUS );
419 gtk_container_add( GTK_CONTAINER(m_widget), m_mainWidget );
420
e1f14d22 421 // for m_mainWidget themes
7d9f12f3
VS
422 gtk_signal_connect( GTK_OBJECT(m_mainWidget), "expose_event",
423 GTK_SIGNAL_FUNC(gtk_window_expose_callback), (gpointer)this );
4e5a4c69 424#ifndef __WXGTK20__
7d9f12f3
VS
425 gtk_signal_connect( GTK_OBJECT(m_mainWidget), "draw",
426 GTK_SIGNAL_FUNC(gtk_window_draw_callback), (gpointer)this );
4e5a4c69 427#endif
7d9f12f3
VS
428
429#ifdef __WXDEBUG__
430 debug_focus_in( m_mainWidget, wxT("wxTopLevelWindowGTK::m_mainWidget"), name );
431#endif
432
e1f14d22 433 // m_wxwindow only represents the client area without toolbar and menubar
7d9f12f3
VS
434 m_wxwindow = gtk_pizza_new();
435 gtk_widget_show( m_wxwindow );
436 gtk_container_add( GTK_CONTAINER(m_mainWidget), m_wxwindow );
437
438#ifdef __WXDEBUG__
439 debug_focus_in( m_wxwindow, wxT("wxTopLevelWindowGTK::m_wxwindow"), name );
440#endif
441
e1f14d22
RR
442 // we donm't allow the frame to get the focus as otherwise
443 // the frame will grab it at arbitrary focus changes
7d9f12f3
VS
444 GTK_WIDGET_UNSET_FLAGS( m_wxwindow, GTK_CAN_FOCUS );
445
446 if (m_parent) m_parent->AddChild( this );
447
e1f14d22 448 // the user resized the frame by dragging etc.
7d9f12f3
VS
449 gtk_signal_connect( GTK_OBJECT(m_widget), "size_allocate",
450 GTK_SIGNAL_FUNC(gtk_frame_size_callback), (gpointer)this );
451
452 PostCreation();
453
454 if ((m_x != -1) || (m_y != -1))
455 gtk_widget_set_uposition( m_widget, m_x, m_y );
e1f14d22
RR
456
457 gtk_window_set_default_size( GTK_WINDOW(m_widget), m_width, m_height );
7d9f12f3 458
e1f14d22
RR
459 // we cannot set MWM hints and icons before the widget has
460 // been realized, so we do this directly after realization
7d9f12f3
VS
461 gtk_signal_connect( GTK_OBJECT(m_widget), "realize",
462 GTK_SIGNAL_FUNC(gtk_frame_realized_callback), (gpointer) this );
463
e1f14d22 464 // the only way to get the window size is to connect to this event
7d9f12f3
VS
465 gtk_signal_connect( GTK_OBJECT(m_widget), "configure_event",
466 GTK_SIGNAL_FUNC(gtk_frame_configure_callback), (gpointer)this );
467
e1f14d22 468 // map and unmap for iconized state
7d9f12f3
VS
469 gtk_signal_connect( GTK_OBJECT(m_widget), "map_event",
470 GTK_SIGNAL_FUNC(gtk_frame_map_callback), (gpointer)this );
471 gtk_signal_connect( GTK_OBJECT(m_widget), "unmap_event",
472 GTK_SIGNAL_FUNC(gtk_frame_unmap_callback), (gpointer)this );
473
e1f14d22 474 // the only way to get the window size is to connect to this event
7d9f12f3
VS
475 gtk_signal_connect( GTK_OBJECT(m_widget), "configure_event",
476 GTK_SIGNAL_FUNC(gtk_frame_configure_callback), (gpointer)this );
477
e1f14d22 478 // disable native tab traversal
7d9f12f3
VS
479 gtk_signal_connect( GTK_OBJECT(m_widget), "focus",
480 GTK_SIGNAL_FUNC(gtk_frame_focus_callback), (gpointer)this );
481
e1f14d22 482 // decorations
f819b4a3
VS
483 if ((m_miniEdge > 0) || (style & wxSIMPLE_BORDER) || (style & wxNO_BORDER))
484 {
485 m_gdkDecor = 0;
486 m_gdkFunc = 0;
487 }
488 else
489 {
490 m_gdkDecor = (long) GDK_DECOR_BORDER;
491 m_gdkFunc = (long) GDK_FUNC_MOVE;
82c9f85c 492
f819b4a3 493 // All this is for Motif Window Manager "hints" and is supposed to be
e1f14d22 494 // recognized by other WMs as well.
f819b4a3
VS
495 if ((style & wxCAPTION) != 0)
496 m_gdkDecor |= GDK_DECOR_TITLE;
497 if ((style & wxSYSTEM_MENU) != 0)
498 {
499 m_gdkFunc |= GDK_FUNC_CLOSE;
500 m_gdkDecor |= GDK_DECOR_MENU;
501 }
502 if ((style & wxMINIMIZE_BOX) != 0)
503 {
504 m_gdkFunc |= GDK_FUNC_MINIMIZE;
505 m_gdkDecor |= GDK_DECOR_MINIMIZE;
506 }
507 if ((style & wxMAXIMIZE_BOX) != 0)
508 {
509 m_gdkFunc |= GDK_FUNC_MAXIMIZE;
510 m_gdkDecor |= GDK_DECOR_MAXIMIZE;
511 }
512 if ((style & wxRESIZE_BORDER) != 0)
513 {
514 m_gdkFunc |= GDK_FUNC_RESIZE;
515 m_gdkDecor |= GDK_DECOR_RESIZEH;
516 }
517 }
518
7d9f12f3
VS
519 return TRUE;
520}
521
522wxTopLevelWindowGTK::~wxTopLevelWindowGTK()
523{
524 m_isBeingDeleted = TRUE;
c6ac78a6 525
710968c3
VZ
526 // it may also be GtkScrolledWindow in the case of an MDI child
527 if (GTK_IS_WINDOW(m_widget))
528 {
529 gtk_window_set_focus( GTK_WINDOW(m_widget), NULL );
530 }
7d9f12f3
VS
531
532 wxTopLevelWindows.DeleteObject( this );
533
534 if (wxTheApp->GetTopWindow() == this)
535 wxTheApp->SetTopWindow( (wxWindow*) NULL );
536
537 if ((wxTopLevelWindows.Number() == 0) &&
538 (wxTheApp->GetExitOnFrameDelete()))
539 {
540 wxTheApp->ExitMainLoop();
541 }
542}
543
544bool wxTopLevelWindowGTK::ShowFullScreen(bool show, long style )
545{
546 if (show == m_fsIsShowing) return FALSE; // return what?
547
548 m_fsIsShowing = show;
549
550 if (show)
551 {
82f2d919
VS
552 m_fsSaveGdkFunc = m_gdkFunc;
553 m_fsSaveGdkDecor = m_gdkDecor;
7d9f12f3
VS
554 m_fsSaveFlag = style;
555 GetPosition( &m_fsSaveFrame.x, &m_fsSaveFrame.y );
556 GetSize( &m_fsSaveFrame.width, &m_fsSaveFrame.height );
557
558 gtk_widget_hide( m_widget );
559 gtk_widget_unrealize( m_widget );
560
82f2d919
VS
561 m_gdkDecor = (long) GDK_DECOR_BORDER;
562 m_gdkFunc = (long) GDK_FUNC_MOVE;
7d9f12f3
VS
563
564 int x;
565 int y;
566 wxDisplaySize( &x, &y );
567 SetSize( 0, 0, x, y );
568
569 gtk_widget_realize( m_widget );
570 gtk_widget_show( m_widget );
571 }
572 else
573 {
574 gtk_widget_hide( m_widget );
575 gtk_widget_unrealize( m_widget );
576
82f2d919
VS
577 m_gdkFunc = m_fsSaveGdkFunc;
578 m_gdkDecor = m_fsSaveGdkDecor;
7d9f12f3
VS
579
580 SetSize( m_fsSaveFrame.x, m_fsSaveFrame.y, m_fsSaveFrame.width, m_fsSaveFrame.height );
581
582 gtk_widget_realize( m_widget );
583 gtk_widget_show( m_widget );
584 }
585
586 return TRUE;
587}
588
589// ----------------------------------------------------------------------------
590// overridden wxWindow methods
591// ----------------------------------------------------------------------------
592
593bool wxTopLevelWindowGTK::Show( bool show )
594{
595 wxASSERT_MSG( (m_widget != NULL), wxT("invalid frame") );
596
597 if (show && !m_sizeSet)
598 {
599 /* by calling GtkOnSize here, we don't have to call
600 either after showing the frame, which would entail
601 much ugly flicker or from within the size_allocate
602 handler, because GTK 1.1.X forbids that. */
603
604 GtkOnSize( m_x, m_y, m_width, m_height );
605 }
606
607 return wxWindow::Show( show );
608}
609
610void wxTopLevelWindowGTK::DoMoveWindow(int WXUNUSED(x), int WXUNUSED(y), int WXUNUSED(width), int WXUNUSED(height) )
611{
612 wxFAIL_MSG( wxT("DoMoveWindow called for wxTopLevelWindowGTK") );
613}
614
615void wxTopLevelWindowGTK::DoSetSize( int x, int y, int width, int height, int sizeFlags )
616{
617 wxASSERT_MSG( (m_widget != NULL), wxT("invalid frame") );
618
e1f14d22 619 // this shouldn't happen: wxFrame, wxMDIParentFrame and wxMDIChildFrame have m_wxwindow
7d9f12f3
VS
620 wxASSERT_MSG( (m_wxwindow != NULL), wxT("invalid frame") );
621
e1f14d22 622 // avoid recursions
7d9f12f3
VS
623 if (m_resizing)
624 return;
625 m_resizing = TRUE;
626
627 int old_x = m_x;
628 int old_y = m_y;
629
630 int old_width = m_width;
631 int old_height = m_height;
632
633 if ((sizeFlags & wxSIZE_ALLOW_MINUS_ONE) == 0)
634 {
635 if (x != -1) m_x = x;
636 if (y != -1) m_y = y;
637 if (width != -1) m_width = width;
638 if (height != -1) m_height = height;
639 }
640 else
641 {
642 m_x = x;
643 m_y = y;
644 m_width = width;
645 m_height = height;
646 }
647
648/*
649 if ((sizeFlags & wxSIZE_AUTO_WIDTH) == wxSIZE_AUTO_WIDTH)
650 {
651 if (width == -1) m_width = 80;
652 }
653
654 if ((sizeFlags & wxSIZE_AUTO_HEIGHT) == wxSIZE_AUTO_HEIGHT)
655 {
656 if (height == -1) m_height = 26;
657 }
658*/
659
e7dda1ff
VS
660 int minWidth = GetMinWidth(),
661 minHeight = GetMinHeight(),
662 maxWidth = GetMaxWidth(),
663 maxHeight = GetMaxHeight();
664
665 if ((minWidth != -1) && (m_width < minWidth)) m_width = minWidth;
666 if ((minHeight != -1) && (m_height < minHeight)) m_height = minHeight;
667 if ((maxWidth != -1) && (m_width > maxWidth)) m_width = maxWidth;
668 if ((maxHeight != -1) && (m_height > maxHeight)) m_height = maxHeight;
7d9f12f3
VS
669
670 if ((m_x != -1) || (m_y != -1))
671 {
672 if ((m_x != old_x) || (m_y != old_y))
673 {
674 gtk_widget_set_uposition( m_widget, m_x, m_y );
675 }
676 }
677
678 if ((m_width != old_width) || (m_height != old_height))
679 {
e1f14d22
RR
680 if (m_widget->window)
681 gdk_window_resize( m_widget->window, m_width, m_height );
682 else
683 gtk_window_set_default_size( GTK_WINDOW(m_widget), m_width, m_height );
7d9f12f3
VS
684
685 /* we set the size in GtkOnSize, i.e. mostly the actual resizing is
686 done either directly before the frame is shown or in idle time
687 so that different calls to SetSize() don't lead to flicker. */
688 m_sizeSet = FALSE;
689 }
690
691 m_resizing = FALSE;
692}
693
694void wxTopLevelWindowGTK::DoGetClientSize( int *width, int *height ) const
695{
696 wxASSERT_MSG( (m_widget != NULL), wxT("invalid frame") );
697
698 wxWindow::DoGetClientSize( width, height );
699 if (height)
700 {
e1f14d22 701 // mini edge
7d9f12f3
VS
702 *height -= m_miniEdge*2 + m_miniTitle;
703 }
704 if (width)
705 {
706 *width -= m_miniEdge*2;
707 }
708}
709
710void wxTopLevelWindowGTK::DoSetClientSize( int width, int height )
711{
712 wxASSERT_MSG( (m_widget != NULL), wxT("invalid frame") );
713
82c9f85c 714 DoSetSize(-1, -1,
7d9f12f3
VS
715 width + m_miniEdge*2, height + m_miniEdge*2 + m_miniTitle, 0);
716}
717
718void wxTopLevelWindowGTK::GtkOnSize( int WXUNUSED(x), int WXUNUSED(y),
82c9f85c 719 int width, int height )
7d9f12f3
VS
720{
721 // due to a bug in gtk, x,y are always 0
722 // m_x = x;
723 // m_y = y;
724
e1f14d22 725 // avoid recursions
7d9f12f3
VS
726 if (m_resizing) return;
727 m_resizing = TRUE;
728
729 if ( m_wxwindow == NULL ) return;
730
731 m_width = width;
732 m_height = height;
733
0d53fc34 734 /* wxMDIChildFrame derives from wxFrame but it _is_ a wxWindow as it uses
7d9f12f3 735 wxWindow::Create to create it's GTK equivalent. m_mainWidget is only
0d53fc34 736 set in wxFrame::Create so it is used to check what kind of frame we
7d9f12f3
VS
737 have here. if m_mainWidget is NULL it is a wxMDIChildFrame and so we
738 skip the part which handles m_frameMenuBar, m_frameToolBar and (most
739 importantly) m_mainWidget */
740
e7dda1ff
VS
741 int minWidth = GetMinWidth(),
742 minHeight = GetMinHeight(),
743 maxWidth = GetMaxWidth(),
744 maxHeight = GetMaxHeight();
745
746 if ((minWidth != -1) && (m_width < minWidth)) m_width = minWidth;
747 if ((minHeight != -1) && (m_height < minHeight)) m_height = minHeight;
748 if ((maxWidth != -1) && (m_width > maxWidth)) m_width = maxWidth;
749 if ((maxHeight != -1) && (m_height > maxHeight)) m_height = maxHeight;
7d9f12f3
VS
750
751 if (m_mainWidget)
752 {
e1f14d22 753 // set size hints
7d9f12f3 754 gint flag = 0; // GDK_HINT_POS;
e7dda1ff
VS
755 if ((minWidth != -1) || (minHeight != -1)) flag |= GDK_HINT_MIN_SIZE;
756 if ((maxWidth != -1) || (maxHeight != -1)) flag |= GDK_HINT_MAX_SIZE;
7d9f12f3 757 GdkGeometry geom;
e7dda1ff
VS
758 geom.min_width = minWidth;
759 geom.min_height = minHeight;
760 geom.max_width = maxWidth;
761 geom.max_height = maxHeight;
7d9f12f3
VS
762 gtk_window_set_geometry_hints( GTK_WINDOW(m_widget),
763 (GtkWidget*) NULL,
764 &geom,
765 (GdkWindowHints) flag );
766
767 /* I revert back to wxGTK's original behaviour. m_mainWidget holds the
768 * menubar, the toolbar and the client area, which is represented by
769 * m_wxwindow.
770 * this hurts in the eye, but I don't want to call SetSize()
771 * because I don't want to call any non-native functions here. */
772
773 int client_x = m_miniEdge;
774 int client_y = m_miniEdge + m_miniTitle;
775 int client_w = m_width - 2*m_miniEdge;
776 int client_h = m_height - 2*m_miniEdge - m_miniTitle;
777 gtk_pizza_set_size( GTK_PIZZA(m_mainWidget),
778 m_wxwindow,
779 client_x, client_y, client_w, client_h );
780 }
781 else
782 {
e1f14d22
RR
783 // If there is no m_mainWidget between m_widget and m_wxwindow there
784 // is no need to set the size or position of m_wxwindow.
7d9f12f3
VS
785 }
786
787 m_sizeSet = TRUE;
788
789 // send size event to frame
790 wxSizeEvent event( wxSize(m_width,m_height), GetId() );
791 event.SetEventObject( this );
792 GetEventHandler()->ProcessEvent( event );
793
794 m_resizing = FALSE;
795}
796
797void wxTopLevelWindowGTK::OnInternalIdle()
798{
799 if (!m_sizeSet && GTK_WIDGET_REALIZED(m_wxwindow))
800 {
801 GtkOnSize( m_x, m_y, m_width, m_height );
802
803 // we'll come back later
804 if (g_isIdle)
805 wxapp_install_idle_handler();
806 return;
807 }
808
809 wxWindow::OnInternalIdle();
810}
811
812
813// ----------------------------------------------------------------------------
814// frame title/icon
815// ----------------------------------------------------------------------------
816
817void wxTopLevelWindowGTK::SetTitle( const wxString &title )
818{
819 wxASSERT_MSG( (m_widget != NULL), wxT("invalid frame") );
820
821 m_title = title;
822 gtk_window_set_title( GTK_WINDOW(m_widget), title.mbc_str() );
823}
824
f618020a 825void wxTopLevelWindowGTK::DoSetIcon( const wxIcon &icon )
7d9f12f3 826{
f618020a 827 if ( !icon.Ok() )
7d9f12f3
VS
828 return;
829
830 if (!m_widget->window)
831 return;
832
833 wxMask *mask = icon.GetMask();
834 GdkBitmap *bm = (GdkBitmap *) NULL;
835 if (mask) bm = mask->GetBitmap();
836
837 gdk_window_set_icon( m_widget->window, (GdkWindow *) NULL, icon.GetPixmap(), bm );
838}
839
f618020a
MB
840void wxTopLevelWindowGTK::SetIcon( const wxIcon &icon )
841{
842 SetIcons( wxIconBundle( icon ) );
843}
844
845void wxTopLevelWindowGTK::SetIcons( const wxIconBundle &icons )
846{
847 wxASSERT_MSG( (m_widget != NULL), wxT("invalid frame") );
848 GdkWindow* window = m_widget->window;
f618020a
MB
849
850 wxTopLevelWindowBase::SetIcons( icons );
851
852 DoSetIcon( icons.GetIcon( -1 ) );
52d6235d
VZ
853 if ( window )
854 {
7efaed4d
MB
855 wxSetIconsX11( (WXDisplay*)GDK_WINDOW_XDISPLAY( window ),
856 (WXWindow)GDK_WINDOW_XWINDOW( window ), icons );
52d6235d 857 }
f618020a
MB
858}
859
7d9f12f3
VS
860// ----------------------------------------------------------------------------
861// frame state: maximized/iconized/normal
862// ----------------------------------------------------------------------------
863
864void wxTopLevelWindowGTK::Maximize(bool WXUNUSED(maximize))
865{
866 wxFAIL_MSG( _T("not implemented") );
867}
868
869bool wxTopLevelWindowGTK::IsMaximized() const
870{
871 // wxFAIL_MSG( _T("not implemented") );
872
873 // This is an approximation
874 return FALSE;
875}
876
877void wxTopLevelWindowGTK::Restore()
878{
879 wxFAIL_MSG( _T("not implemented") );
880}
881
882void wxTopLevelWindowGTK::Iconize( bool iconize )
883{
884 if (iconize)
885 {
886 GdkWindow *window = m_widget->window;
887
888 // you should do it later, for example from OnCreate() handler
889 wxCHECK_RET( window, _T("frame not created yet - can't iconize") );
890
891 XIconifyWindow( GDK_WINDOW_XDISPLAY( window ),
892 GDK_WINDOW_XWINDOW( window ),
893 DefaultScreen( GDK_DISPLAY() ) );
894 }
895}
896
897bool wxTopLevelWindowGTK::IsIconized() const
898{
899 return m_isIconized;
900}
901
902void wxTopLevelWindowGTK::SetIconizeState(bool iconize)
903{
904 if ( iconize != m_isIconized )
905 {
906 m_isIconized = iconize;
907 (void)SendIconizeEvent(iconize);
908 }
909}
910