]> git.saurik.com Git - wxWidgets.git/blame - src/gtk/toplevel.cpp
fixed VC++ warning in optimized build
[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
266
267static void gtk_window_draw_callback( GtkWidget *widget, GdkRectangle *rect, wxWindow *win )
268{
269 GtkPizza *pizza = GTK_PIZZA(widget);
270
90350682
VZ
271 gtk_paint_flat_box (win->m_widget->style,
272 pizza->bin_window, GTK_STATE_NORMAL,
273 GTK_SHADOW_NONE,
274 rect,
275 win->m_widget,
276 (char *)"base",
277 0, 0, -1, -1);
7d9f12f3
VS
278}
279
280// ----------------------------------------------------------------------------
281// wxTopLevelWindowGTK itself
282// ----------------------------------------------------------------------------
283
284//-----------------------------------------------------------------------------
285// InsertChild for wxTopLevelWindowGTK
286//-----------------------------------------------------------------------------
287
288/* Callback for wxTopLevelWindowGTK. This very strange beast has to be used because
289 * C++ has no virtual methods in a constructor. We have to emulate a
290 * virtual function here as wxWindows requires different ways to insert
291 * a child in container classes. */
292
293static void wxInsertChildInTopLevelWindow( wxTopLevelWindowGTK* parent, wxWindow* child )
294{
295 wxASSERT( GTK_IS_WIDGET(child->m_widget) );
296
297 if (!parent->m_insertInClientArea)
298 {
e1f14d22 299 // these are outside the client area
7d9f12f3
VS
300 wxTopLevelWindowGTK* frame = (wxTopLevelWindowGTK*) parent;
301 gtk_pizza_put( GTK_PIZZA(frame->m_mainWidget),
302 GTK_WIDGET(child->m_widget),
303 child->m_x,
304 child->m_y,
305 child->m_width,
306 child->m_height );
307 }
308 else
309 {
e1f14d22 310 // these are inside the client area
7d9f12f3
VS
311 gtk_pizza_put( GTK_PIZZA(parent->m_wxwindow),
312 GTK_WIDGET(child->m_widget),
e4b7b2b0
VS
313 child->m_x,
314 child->m_y,
7d9f12f3
VS
315 child->m_width,
316 child->m_height );
317 }
318
e1f14d22 319 // resize on OnInternalIdle
7d9f12f3
VS
320 parent->GtkUpdateSize();
321}
322
323// ----------------------------------------------------------------------------
324// wxTopLevelWindowGTK creation
325// ----------------------------------------------------------------------------
326
327void wxTopLevelWindowGTK::Init()
328{
329 m_sizeSet = FALSE;
330 m_miniEdge = 0;
331 m_miniTitle = 0;
332 m_mainWidget = (GtkWidget*) NULL;
333 m_insertInClientArea = TRUE;
334 m_isFrame = TRUE;
335 m_isIconized = FALSE;
336 m_fsIsShowing = FALSE;
337 m_themeEnabled = TRUE;
f819b4a3 338 m_gdkDecor = m_gdkFunc = 0;
7d9f12f3
VS
339}
340
341bool wxTopLevelWindowGTK::Create( wxWindow *parent,
f819b4a3
VS
342 wxWindowID id,
343 const wxString& title,
344 const wxPoint& pos,
345 const wxSize& sizeOrig,
346 long style,
347 const wxString &name )
7d9f12f3
VS
348{
349 // always create a frame of some reasonable, even if arbitrary, size (at
350 // least for MSW compatibility)
351 wxSize size = sizeOrig;
352 if ( size.x == -1 || size.y == -1 )
353 {
354 wxSize sizeDpy = wxGetDisplaySize();
355 if ( size.x == -1 )
356 size.x = sizeDpy.x / 3;
357 if ( size.y == -1 )
358 size.y = sizeDpy.y / 5;
359 }
360
361 wxTopLevelWindows.Append( this );
362
363 m_needParent = FALSE;
2c990ec0 364
7d9f12f3
VS
365 if (!PreCreation( parent, pos, size ) ||
366 !CreateBase( parent, id, pos, size, style, wxDefaultValidator, name ))
367 {
368 wxFAIL_MSG( wxT("wxTopLevelWindowGTK creation failed") );
369 return FALSE;
370 }
371
372 m_title = title;
373
374 m_insertCallback = (wxInsertChildFunction) wxInsertChildInTopLevelWindow;
375
376 GtkWindowType win_type = GTK_WINDOW_TOPLEVEL;
377
378 if (style & wxFRAME_TOOL_WINDOW)
379 win_type = GTK_WINDOW_POPUP;
82c9f85c 380
f819b4a3 381 if (GetExtraStyle() & wxTOPLEVEL_EX_DIALOG)
9e691f46
VZ
382 {
383 // there is no more GTK_WINDOW_DIALOG in 2.0
384#ifdef __WXGTK20__
385 win_type = GTK_WINDOW_TOPLEVEL;
386#else
7d9f12f3 387 win_type = GTK_WINDOW_DIALOG;
9e691f46
VZ
388#endif
389 }
7d9f12f3
VS
390
391 m_widget = gtk_window_new( win_type );
392
7cd95599 393 if (m_parent && (GTK_IS_WINDOW(m_parent->m_widget)) &&
2c990ec0 394 (GetExtraStyle() & wxTOPLEVEL_EX_DIALOG))
7cd95599 395 {
7d9f12f3 396 gtk_window_set_transient_for( GTK_WINDOW(m_widget), GTK_WINDOW(m_parent->m_widget) );
7cd95599 397 }
7d9f12f3
VS
398
399 if (!name.IsEmpty())
400 gtk_window_set_wmclass( GTK_WINDOW(m_widget), name.mb_str(), name.mb_str() );
401
402#ifdef __WXDEBUG__
403 debug_focus_in( m_widget, wxT("wxTopLevelWindowGTK::m_widget"), name );
404#endif
405
406 gtk_window_set_title( GTK_WINDOW(m_widget), title.mbc_str() );
407 GTK_WIDGET_UNSET_FLAGS( m_widget, GTK_CAN_FOCUS );
408
409 gtk_signal_connect( GTK_OBJECT(m_widget), "delete_event",
410 GTK_SIGNAL_FUNC(gtk_frame_delete_callback), (gpointer)this );
411
e1f14d22 412 // m_mainWidget holds the toolbar, the menubar and the client area
7d9f12f3
VS
413 m_mainWidget = gtk_pizza_new();
414 gtk_widget_show( m_mainWidget );
415 GTK_WIDGET_UNSET_FLAGS( m_mainWidget, GTK_CAN_FOCUS );
416 gtk_container_add( GTK_CONTAINER(m_widget), m_mainWidget );
417
e1f14d22 418 // for m_mainWidget themes
7d9f12f3
VS
419 gtk_signal_connect( GTK_OBJECT(m_mainWidget), "expose_event",
420 GTK_SIGNAL_FUNC(gtk_window_expose_callback), (gpointer)this );
421 gtk_signal_connect( GTK_OBJECT(m_mainWidget), "draw",
422 GTK_SIGNAL_FUNC(gtk_window_draw_callback), (gpointer)this );
423
424#ifdef __WXDEBUG__
425 debug_focus_in( m_mainWidget, wxT("wxTopLevelWindowGTK::m_mainWidget"), name );
426#endif
427
e1f14d22 428 // m_wxwindow only represents the client area without toolbar and menubar
7d9f12f3
VS
429 m_wxwindow = gtk_pizza_new();
430 gtk_widget_show( m_wxwindow );
431 gtk_container_add( GTK_CONTAINER(m_mainWidget), m_wxwindow );
432
433#ifdef __WXDEBUG__
434 debug_focus_in( m_wxwindow, wxT("wxTopLevelWindowGTK::m_wxwindow"), name );
435#endif
436
e1f14d22
RR
437 // we donm't allow the frame to get the focus as otherwise
438 // the frame will grab it at arbitrary focus changes
7d9f12f3
VS
439 GTK_WIDGET_UNSET_FLAGS( m_wxwindow, GTK_CAN_FOCUS );
440
441 if (m_parent) m_parent->AddChild( this );
442
e1f14d22 443 // the user resized the frame by dragging etc.
7d9f12f3
VS
444 gtk_signal_connect( GTK_OBJECT(m_widget), "size_allocate",
445 GTK_SIGNAL_FUNC(gtk_frame_size_callback), (gpointer)this );
446
447 PostCreation();
448
449 if ((m_x != -1) || (m_y != -1))
450 gtk_widget_set_uposition( m_widget, m_x, m_y );
e1f14d22
RR
451
452 gtk_window_set_default_size( GTK_WINDOW(m_widget), m_width, m_height );
7d9f12f3 453
e1f14d22
RR
454 // we cannot set MWM hints and icons before the widget has
455 // been realized, so we do this directly after realization
7d9f12f3
VS
456 gtk_signal_connect( GTK_OBJECT(m_widget), "realize",
457 GTK_SIGNAL_FUNC(gtk_frame_realized_callback), (gpointer) this );
458
e1f14d22 459 // the only way to get the window size is to connect to this event
7d9f12f3
VS
460 gtk_signal_connect( GTK_OBJECT(m_widget), "configure_event",
461 GTK_SIGNAL_FUNC(gtk_frame_configure_callback), (gpointer)this );
462
e1f14d22 463 // map and unmap for iconized state
7d9f12f3
VS
464 gtk_signal_connect( GTK_OBJECT(m_widget), "map_event",
465 GTK_SIGNAL_FUNC(gtk_frame_map_callback), (gpointer)this );
466 gtk_signal_connect( GTK_OBJECT(m_widget), "unmap_event",
467 GTK_SIGNAL_FUNC(gtk_frame_unmap_callback), (gpointer)this );
468
e1f14d22 469 // the only way to get the window size is to connect to this event
7d9f12f3
VS
470 gtk_signal_connect( GTK_OBJECT(m_widget), "configure_event",
471 GTK_SIGNAL_FUNC(gtk_frame_configure_callback), (gpointer)this );
472
e1f14d22 473 // disable native tab traversal
7d9f12f3
VS
474 gtk_signal_connect( GTK_OBJECT(m_widget), "focus",
475 GTK_SIGNAL_FUNC(gtk_frame_focus_callback), (gpointer)this );
476
e1f14d22 477 // decorations
f819b4a3
VS
478 if ((m_miniEdge > 0) || (style & wxSIMPLE_BORDER) || (style & wxNO_BORDER))
479 {
480 m_gdkDecor = 0;
481 m_gdkFunc = 0;
482 }
483 else
484 {
485 m_gdkDecor = (long) GDK_DECOR_BORDER;
486 m_gdkFunc = (long) GDK_FUNC_MOVE;
82c9f85c 487
f819b4a3 488 // All this is for Motif Window Manager "hints" and is supposed to be
e1f14d22 489 // recognized by other WMs as well.
f819b4a3
VS
490 if ((style & wxCAPTION) != 0)
491 m_gdkDecor |= GDK_DECOR_TITLE;
492 if ((style & wxSYSTEM_MENU) != 0)
493 {
494 m_gdkFunc |= GDK_FUNC_CLOSE;
495 m_gdkDecor |= GDK_DECOR_MENU;
496 }
497 if ((style & wxMINIMIZE_BOX) != 0)
498 {
499 m_gdkFunc |= GDK_FUNC_MINIMIZE;
500 m_gdkDecor |= GDK_DECOR_MINIMIZE;
501 }
502 if ((style & wxMAXIMIZE_BOX) != 0)
503 {
504 m_gdkFunc |= GDK_FUNC_MAXIMIZE;
505 m_gdkDecor |= GDK_DECOR_MAXIMIZE;
506 }
507 if ((style & wxRESIZE_BORDER) != 0)
508 {
509 m_gdkFunc |= GDK_FUNC_RESIZE;
510 m_gdkDecor |= GDK_DECOR_RESIZEH;
511 }
512 }
513
7d9f12f3
VS
514 return TRUE;
515}
516
517wxTopLevelWindowGTK::~wxTopLevelWindowGTK()
518{
519 m_isBeingDeleted = TRUE;
c6ac78a6 520
710968c3
VZ
521 // it may also be GtkScrolledWindow in the case of an MDI child
522 if (GTK_IS_WINDOW(m_widget))
523 {
524 gtk_window_set_focus( GTK_WINDOW(m_widget), NULL );
525 }
7d9f12f3
VS
526
527 wxTopLevelWindows.DeleteObject( this );
528
529 if (wxTheApp->GetTopWindow() == this)
530 wxTheApp->SetTopWindow( (wxWindow*) NULL );
531
532 if ((wxTopLevelWindows.Number() == 0) &&
533 (wxTheApp->GetExitOnFrameDelete()))
534 {
535 wxTheApp->ExitMainLoop();
536 }
537}
538
539bool wxTopLevelWindowGTK::ShowFullScreen(bool show, long style )
540{
541 if (show == m_fsIsShowing) return FALSE; // return what?
542
543 m_fsIsShowing = show;
544
545 if (show)
546 {
82f2d919
VS
547 m_fsSaveGdkFunc = m_gdkFunc;
548 m_fsSaveGdkDecor = m_gdkDecor;
7d9f12f3
VS
549 m_fsSaveFlag = style;
550 GetPosition( &m_fsSaveFrame.x, &m_fsSaveFrame.y );
551 GetSize( &m_fsSaveFrame.width, &m_fsSaveFrame.height );
552
553 gtk_widget_hide( m_widget );
554 gtk_widget_unrealize( m_widget );
555
82f2d919
VS
556 m_gdkDecor = (long) GDK_DECOR_BORDER;
557 m_gdkFunc = (long) GDK_FUNC_MOVE;
7d9f12f3
VS
558
559 int x;
560 int y;
561 wxDisplaySize( &x, &y );
562 SetSize( 0, 0, x, y );
563
564 gtk_widget_realize( m_widget );
565 gtk_widget_show( m_widget );
566 }
567 else
568 {
569 gtk_widget_hide( m_widget );
570 gtk_widget_unrealize( m_widget );
571
82f2d919
VS
572 m_gdkFunc = m_fsSaveGdkFunc;
573 m_gdkDecor = m_fsSaveGdkDecor;
7d9f12f3
VS
574
575 SetSize( m_fsSaveFrame.x, m_fsSaveFrame.y, m_fsSaveFrame.width, m_fsSaveFrame.height );
576
577 gtk_widget_realize( m_widget );
578 gtk_widget_show( m_widget );
579 }
580
581 return TRUE;
582}
583
584// ----------------------------------------------------------------------------
585// overridden wxWindow methods
586// ----------------------------------------------------------------------------
587
588bool wxTopLevelWindowGTK::Show( bool show )
589{
590 wxASSERT_MSG( (m_widget != NULL), wxT("invalid frame") );
591
592 if (show && !m_sizeSet)
593 {
594 /* by calling GtkOnSize here, we don't have to call
595 either after showing the frame, which would entail
596 much ugly flicker or from within the size_allocate
597 handler, because GTK 1.1.X forbids that. */
598
599 GtkOnSize( m_x, m_y, m_width, m_height );
600 }
601
602 return wxWindow::Show( show );
603}
604
605void wxTopLevelWindowGTK::DoMoveWindow(int WXUNUSED(x), int WXUNUSED(y), int WXUNUSED(width), int WXUNUSED(height) )
606{
607 wxFAIL_MSG( wxT("DoMoveWindow called for wxTopLevelWindowGTK") );
608}
609
610void wxTopLevelWindowGTK::DoSetSize( int x, int y, int width, int height, int sizeFlags )
611{
612 wxASSERT_MSG( (m_widget != NULL), wxT("invalid frame") );
613
e1f14d22 614 // this shouldn't happen: wxFrame, wxMDIParentFrame and wxMDIChildFrame have m_wxwindow
7d9f12f3
VS
615 wxASSERT_MSG( (m_wxwindow != NULL), wxT("invalid frame") );
616
e1f14d22 617 // avoid recursions
7d9f12f3
VS
618 if (m_resizing)
619 return;
620 m_resizing = TRUE;
621
622 int old_x = m_x;
623 int old_y = m_y;
624
625 int old_width = m_width;
626 int old_height = m_height;
627
628 if ((sizeFlags & wxSIZE_ALLOW_MINUS_ONE) == 0)
629 {
630 if (x != -1) m_x = x;
631 if (y != -1) m_y = y;
632 if (width != -1) m_width = width;
633 if (height != -1) m_height = height;
634 }
635 else
636 {
637 m_x = x;
638 m_y = y;
639 m_width = width;
640 m_height = height;
641 }
642
643/*
644 if ((sizeFlags & wxSIZE_AUTO_WIDTH) == wxSIZE_AUTO_WIDTH)
645 {
646 if (width == -1) m_width = 80;
647 }
648
649 if ((sizeFlags & wxSIZE_AUTO_HEIGHT) == wxSIZE_AUTO_HEIGHT)
650 {
651 if (height == -1) m_height = 26;
652 }
653*/
654
e7dda1ff
VS
655 int minWidth = GetMinWidth(),
656 minHeight = GetMinHeight(),
657 maxWidth = GetMaxWidth(),
658 maxHeight = GetMaxHeight();
659
660 if ((minWidth != -1) && (m_width < minWidth)) m_width = minWidth;
661 if ((minHeight != -1) && (m_height < minHeight)) m_height = minHeight;
662 if ((maxWidth != -1) && (m_width > maxWidth)) m_width = maxWidth;
663 if ((maxHeight != -1) && (m_height > maxHeight)) m_height = maxHeight;
7d9f12f3
VS
664
665 if ((m_x != -1) || (m_y != -1))
666 {
667 if ((m_x != old_x) || (m_y != old_y))
668 {
669 gtk_widget_set_uposition( m_widget, m_x, m_y );
670 }
671 }
672
673 if ((m_width != old_width) || (m_height != old_height))
674 {
e1f14d22
RR
675 if (m_widget->window)
676 gdk_window_resize( m_widget->window, m_width, m_height );
677 else
678 gtk_window_set_default_size( GTK_WINDOW(m_widget), m_width, m_height );
7d9f12f3
VS
679
680 /* we set the size in GtkOnSize, i.e. mostly the actual resizing is
681 done either directly before the frame is shown or in idle time
682 so that different calls to SetSize() don't lead to flicker. */
683 m_sizeSet = FALSE;
684 }
685
686 m_resizing = FALSE;
687}
688
689void wxTopLevelWindowGTK::DoGetClientSize( int *width, int *height ) const
690{
691 wxASSERT_MSG( (m_widget != NULL), wxT("invalid frame") );
692
693 wxWindow::DoGetClientSize( width, height );
694 if (height)
695 {
e1f14d22 696 // mini edge
7d9f12f3
VS
697 *height -= m_miniEdge*2 + m_miniTitle;
698 }
699 if (width)
700 {
701 *width -= m_miniEdge*2;
702 }
703}
704
705void wxTopLevelWindowGTK::DoSetClientSize( int width, int height )
706{
707 wxASSERT_MSG( (m_widget != NULL), wxT("invalid frame") );
708
82c9f85c 709 DoSetSize(-1, -1,
7d9f12f3
VS
710 width + m_miniEdge*2, height + m_miniEdge*2 + m_miniTitle, 0);
711}
712
713void wxTopLevelWindowGTK::GtkOnSize( int WXUNUSED(x), int WXUNUSED(y),
82c9f85c 714 int width, int height )
7d9f12f3
VS
715{
716 // due to a bug in gtk, x,y are always 0
717 // m_x = x;
718 // m_y = y;
719
e1f14d22 720 // avoid recursions
7d9f12f3
VS
721 if (m_resizing) return;
722 m_resizing = TRUE;
723
724 if ( m_wxwindow == NULL ) return;
725
726 m_width = width;
727 m_height = height;
728
0d53fc34 729 /* wxMDIChildFrame derives from wxFrame but it _is_ a wxWindow as it uses
7d9f12f3 730 wxWindow::Create to create it's GTK equivalent. m_mainWidget is only
0d53fc34 731 set in wxFrame::Create so it is used to check what kind of frame we
7d9f12f3
VS
732 have here. if m_mainWidget is NULL it is a wxMDIChildFrame and so we
733 skip the part which handles m_frameMenuBar, m_frameToolBar and (most
734 importantly) m_mainWidget */
735
e7dda1ff
VS
736 int minWidth = GetMinWidth(),
737 minHeight = GetMinHeight(),
738 maxWidth = GetMaxWidth(),
739 maxHeight = GetMaxHeight();
740
741 if ((minWidth != -1) && (m_width < minWidth)) m_width = minWidth;
742 if ((minHeight != -1) && (m_height < minHeight)) m_height = minHeight;
743 if ((maxWidth != -1) && (m_width > maxWidth)) m_width = maxWidth;
744 if ((maxHeight != -1) && (m_height > maxHeight)) m_height = maxHeight;
7d9f12f3
VS
745
746 if (m_mainWidget)
747 {
e1f14d22 748 // set size hints
7d9f12f3 749 gint flag = 0; // GDK_HINT_POS;
e7dda1ff
VS
750 if ((minWidth != -1) || (minHeight != -1)) flag |= GDK_HINT_MIN_SIZE;
751 if ((maxWidth != -1) || (maxHeight != -1)) flag |= GDK_HINT_MAX_SIZE;
7d9f12f3 752 GdkGeometry geom;
e7dda1ff
VS
753 geom.min_width = minWidth;
754 geom.min_height = minHeight;
755 geom.max_width = maxWidth;
756 geom.max_height = maxHeight;
7d9f12f3
VS
757 gtk_window_set_geometry_hints( GTK_WINDOW(m_widget),
758 (GtkWidget*) NULL,
759 &geom,
760 (GdkWindowHints) flag );
761
762 /* I revert back to wxGTK's original behaviour. m_mainWidget holds the
763 * menubar, the toolbar and the client area, which is represented by
764 * m_wxwindow.
765 * this hurts in the eye, but I don't want to call SetSize()
766 * because I don't want to call any non-native functions here. */
767
768 int client_x = m_miniEdge;
769 int client_y = m_miniEdge + m_miniTitle;
770 int client_w = m_width - 2*m_miniEdge;
771 int client_h = m_height - 2*m_miniEdge - m_miniTitle;
772 gtk_pizza_set_size( GTK_PIZZA(m_mainWidget),
773 m_wxwindow,
774 client_x, client_y, client_w, client_h );
775 }
776 else
777 {
e1f14d22
RR
778 // If there is no m_mainWidget between m_widget and m_wxwindow there
779 // is no need to set the size or position of m_wxwindow.
7d9f12f3
VS
780 }
781
782 m_sizeSet = TRUE;
783
784 // send size event to frame
785 wxSizeEvent event( wxSize(m_width,m_height), GetId() );
786 event.SetEventObject( this );
787 GetEventHandler()->ProcessEvent( event );
788
789 m_resizing = FALSE;
790}
791
792void wxTopLevelWindowGTK::OnInternalIdle()
793{
794 if (!m_sizeSet && GTK_WIDGET_REALIZED(m_wxwindow))
795 {
796 GtkOnSize( m_x, m_y, m_width, m_height );
797
798 // we'll come back later
799 if (g_isIdle)
800 wxapp_install_idle_handler();
801 return;
802 }
803
804 wxWindow::OnInternalIdle();
805}
806
807
808// ----------------------------------------------------------------------------
809// frame title/icon
810// ----------------------------------------------------------------------------
811
812void wxTopLevelWindowGTK::SetTitle( const wxString &title )
813{
814 wxASSERT_MSG( (m_widget != NULL), wxT("invalid frame") );
815
816 m_title = title;
817 gtk_window_set_title( GTK_WINDOW(m_widget), title.mbc_str() );
818}
819
f618020a 820void wxTopLevelWindowGTK::DoSetIcon( const wxIcon &icon )
7d9f12f3 821{
f618020a 822 if ( !icon.Ok() )
7d9f12f3
VS
823 return;
824
825 if (!m_widget->window)
826 return;
827
828 wxMask *mask = icon.GetMask();
829 GdkBitmap *bm = (GdkBitmap *) NULL;
830 if (mask) bm = mask->GetBitmap();
831
832 gdk_window_set_icon( m_widget->window, (GdkWindow *) NULL, icon.GetPixmap(), bm );
833}
834
f618020a
MB
835void wxTopLevelWindowGTK::SetIcon( const wxIcon &icon )
836{
837 SetIcons( wxIconBundle( icon ) );
838}
839
840void wxTopLevelWindowGTK::SetIcons( const wxIconBundle &icons )
841{
842 wxASSERT_MSG( (m_widget != NULL), wxT("invalid frame") );
843 GdkWindow* window = m_widget->window;
f618020a
MB
844
845 wxTopLevelWindowBase::SetIcons( icons );
846
847 DoSetIcon( icons.GetIcon( -1 ) );
7efaed4d
MB
848 if( window )
849 wxSetIconsX11( (WXDisplay*)GDK_WINDOW_XDISPLAY( window ),
850 (WXWindow)GDK_WINDOW_XWINDOW( window ), icons );
f618020a
MB
851}
852
7d9f12f3
VS
853// ----------------------------------------------------------------------------
854// frame state: maximized/iconized/normal
855// ----------------------------------------------------------------------------
856
857void wxTopLevelWindowGTK::Maximize(bool WXUNUSED(maximize))
858{
859 wxFAIL_MSG( _T("not implemented") );
860}
861
862bool wxTopLevelWindowGTK::IsMaximized() const
863{
864 // wxFAIL_MSG( _T("not implemented") );
865
866 // This is an approximation
867 return FALSE;
868}
869
870void wxTopLevelWindowGTK::Restore()
871{
872 wxFAIL_MSG( _T("not implemented") );
873}
874
875void wxTopLevelWindowGTK::Iconize( bool iconize )
876{
877 if (iconize)
878 {
879 GdkWindow *window = m_widget->window;
880
881 // you should do it later, for example from OnCreate() handler
882 wxCHECK_RET( window, _T("frame not created yet - can't iconize") );
883
884 XIconifyWindow( GDK_WINDOW_XDISPLAY( window ),
885 GDK_WINDOW_XWINDOW( window ),
886 DefaultScreen( GDK_DISPLAY() ) );
887 }
888}
889
890bool wxTopLevelWindowGTK::IsIconized() const
891{
892 return m_isIconized;
893}
894
895void wxTopLevelWindowGTK::SetIconizeState(bool iconize)
896{
897 if ( iconize != m_isIconized )
898 {
899 m_isIconized = iconize;
900 (void)SendIconizeEvent(iconize);
901 }
902}
903