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