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