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