]> git.saurik.com Git - wxWidgets.git/blame - src/gtk/toplevel.cpp
A bit of scrolling works under GTK 2.0
[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 );
4e5a4c69 421#ifndef __WXGTK20__
7d9f12f3
VS
422 gtk_signal_connect( GTK_OBJECT(m_mainWidget), "draw",
423 GTK_SIGNAL_FUNC(gtk_window_draw_callback), (gpointer)this );
4e5a4c69 424#endif
7d9f12f3
VS
425
426#ifdef __WXDEBUG__
427 debug_focus_in( m_mainWidget, wxT("wxTopLevelWindowGTK::m_mainWidget"), name );
428#endif
429
e1f14d22 430 // m_wxwindow only represents the client area without toolbar and menubar
7d9f12f3
VS
431 m_wxwindow = gtk_pizza_new();
432 gtk_widget_show( m_wxwindow );
433 gtk_container_add( GTK_CONTAINER(m_mainWidget), m_wxwindow );
434
435#ifdef __WXDEBUG__
436 debug_focus_in( m_wxwindow, wxT("wxTopLevelWindowGTK::m_wxwindow"), name );
437#endif
438
e1f14d22
RR
439 // we donm't allow the frame to get the focus as otherwise
440 // the frame will grab it at arbitrary focus changes
7d9f12f3
VS
441 GTK_WIDGET_UNSET_FLAGS( m_wxwindow, GTK_CAN_FOCUS );
442
443 if (m_parent) m_parent->AddChild( this );
444
e1f14d22 445 // the user resized the frame by dragging etc.
7d9f12f3
VS
446 gtk_signal_connect( GTK_OBJECT(m_widget), "size_allocate",
447 GTK_SIGNAL_FUNC(gtk_frame_size_callback), (gpointer)this );
448
449 PostCreation();
450
451 if ((m_x != -1) || (m_y != -1))
452 gtk_widget_set_uposition( m_widget, m_x, m_y );
e1f14d22
RR
453
454 gtk_window_set_default_size( GTK_WINDOW(m_widget), m_width, m_height );
7d9f12f3 455
e1f14d22
RR
456 // we cannot set MWM hints and icons before the widget has
457 // been realized, so we do this directly after realization
7d9f12f3
VS
458 gtk_signal_connect( GTK_OBJECT(m_widget), "realize",
459 GTK_SIGNAL_FUNC(gtk_frame_realized_callback), (gpointer) this );
460
e1f14d22 461 // the only way to get the window size is to connect to this event
7d9f12f3
VS
462 gtk_signal_connect( GTK_OBJECT(m_widget), "configure_event",
463 GTK_SIGNAL_FUNC(gtk_frame_configure_callback), (gpointer)this );
464
e1f14d22 465 // map and unmap for iconized state
7d9f12f3
VS
466 gtk_signal_connect( GTK_OBJECT(m_widget), "map_event",
467 GTK_SIGNAL_FUNC(gtk_frame_map_callback), (gpointer)this );
468 gtk_signal_connect( GTK_OBJECT(m_widget), "unmap_event",
469 GTK_SIGNAL_FUNC(gtk_frame_unmap_callback), (gpointer)this );
470
e1f14d22 471 // the only way to get the window size is to connect to this event
7d9f12f3
VS
472 gtk_signal_connect( GTK_OBJECT(m_widget), "configure_event",
473 GTK_SIGNAL_FUNC(gtk_frame_configure_callback), (gpointer)this );
474
e1f14d22 475 // disable native tab traversal
7d9f12f3
VS
476 gtk_signal_connect( GTK_OBJECT(m_widget), "focus",
477 GTK_SIGNAL_FUNC(gtk_frame_focus_callback), (gpointer)this );
478
e1f14d22 479 // decorations
f819b4a3
VS
480 if ((m_miniEdge > 0) || (style & wxSIMPLE_BORDER) || (style & wxNO_BORDER))
481 {
482 m_gdkDecor = 0;
483 m_gdkFunc = 0;
484 }
485 else
486 {
487 m_gdkDecor = (long) GDK_DECOR_BORDER;
488 m_gdkFunc = (long) GDK_FUNC_MOVE;
82c9f85c 489
f819b4a3 490 // All this is for Motif Window Manager "hints" and is supposed to be
e1f14d22 491 // recognized by other WMs as well.
f819b4a3
VS
492 if ((style & wxCAPTION) != 0)
493 m_gdkDecor |= GDK_DECOR_TITLE;
494 if ((style & wxSYSTEM_MENU) != 0)
495 {
496 m_gdkFunc |= GDK_FUNC_CLOSE;
497 m_gdkDecor |= GDK_DECOR_MENU;
498 }
499 if ((style & wxMINIMIZE_BOX) != 0)
500 {
501 m_gdkFunc |= GDK_FUNC_MINIMIZE;
502 m_gdkDecor |= GDK_DECOR_MINIMIZE;
503 }
504 if ((style & wxMAXIMIZE_BOX) != 0)
505 {
506 m_gdkFunc |= GDK_FUNC_MAXIMIZE;
507 m_gdkDecor |= GDK_DECOR_MAXIMIZE;
508 }
509 if ((style & wxRESIZE_BORDER) != 0)
510 {
511 m_gdkFunc |= GDK_FUNC_RESIZE;
512 m_gdkDecor |= GDK_DECOR_RESIZEH;
513 }
514 }
515
7d9f12f3
VS
516 return TRUE;
517}
518
519wxTopLevelWindowGTK::~wxTopLevelWindowGTK()
520{
521 m_isBeingDeleted = TRUE;
c6ac78a6 522
710968c3
VZ
523 // it may also be GtkScrolledWindow in the case of an MDI child
524 if (GTK_IS_WINDOW(m_widget))
525 {
526 gtk_window_set_focus( GTK_WINDOW(m_widget), NULL );
527 }
7d9f12f3
VS
528
529 wxTopLevelWindows.DeleteObject( this );
530
531 if (wxTheApp->GetTopWindow() == this)
532 wxTheApp->SetTopWindow( (wxWindow*) NULL );
533
534 if ((wxTopLevelWindows.Number() == 0) &&
535 (wxTheApp->GetExitOnFrameDelete()))
536 {
537 wxTheApp->ExitMainLoop();
538 }
539}
540
541bool wxTopLevelWindowGTK::ShowFullScreen(bool show, long style )
542{
543 if (show == m_fsIsShowing) return FALSE; // return what?
544
545 m_fsIsShowing = show;
546
547 if (show)
548 {
82f2d919
VS
549 m_fsSaveGdkFunc = m_gdkFunc;
550 m_fsSaveGdkDecor = m_gdkDecor;
7d9f12f3
VS
551 m_fsSaveFlag = style;
552 GetPosition( &m_fsSaveFrame.x, &m_fsSaveFrame.y );
553 GetSize( &m_fsSaveFrame.width, &m_fsSaveFrame.height );
554
555 gtk_widget_hide( m_widget );
556 gtk_widget_unrealize( m_widget );
557
82f2d919
VS
558 m_gdkDecor = (long) GDK_DECOR_BORDER;
559 m_gdkFunc = (long) GDK_FUNC_MOVE;
7d9f12f3
VS
560
561 int x;
562 int y;
563 wxDisplaySize( &x, &y );
564 SetSize( 0, 0, x, y );
565
566 gtk_widget_realize( m_widget );
567 gtk_widget_show( m_widget );
568 }
569 else
570 {
571 gtk_widget_hide( m_widget );
572 gtk_widget_unrealize( m_widget );
573
82f2d919
VS
574 m_gdkFunc = m_fsSaveGdkFunc;
575 m_gdkDecor = m_fsSaveGdkDecor;
7d9f12f3
VS
576
577 SetSize( m_fsSaveFrame.x, m_fsSaveFrame.y, m_fsSaveFrame.width, m_fsSaveFrame.height );
578
579 gtk_widget_realize( m_widget );
580 gtk_widget_show( m_widget );
581 }
582
583 return TRUE;
584}
585
586// ----------------------------------------------------------------------------
587// overridden wxWindow methods
588// ----------------------------------------------------------------------------
589
590bool wxTopLevelWindowGTK::Show( bool show )
591{
592 wxASSERT_MSG( (m_widget != NULL), wxT("invalid frame") );
593
594 if (show && !m_sizeSet)
595 {
596 /* by calling GtkOnSize here, we don't have to call
597 either after showing the frame, which would entail
598 much ugly flicker or from within the size_allocate
599 handler, because GTK 1.1.X forbids that. */
600
601 GtkOnSize( m_x, m_y, m_width, m_height );
602 }
603
604 return wxWindow::Show( show );
605}
606
607void wxTopLevelWindowGTK::DoMoveWindow(int WXUNUSED(x), int WXUNUSED(y), int WXUNUSED(width), int WXUNUSED(height) )
608{
609 wxFAIL_MSG( wxT("DoMoveWindow called for wxTopLevelWindowGTK") );
610}
611
612void wxTopLevelWindowGTK::DoSetSize( int x, int y, int width, int height, int sizeFlags )
613{
614 wxASSERT_MSG( (m_widget != NULL), wxT("invalid frame") );
615
e1f14d22 616 // this shouldn't happen: wxFrame, wxMDIParentFrame and wxMDIChildFrame have m_wxwindow
7d9f12f3
VS
617 wxASSERT_MSG( (m_wxwindow != NULL), wxT("invalid frame") );
618
e1f14d22 619 // avoid recursions
7d9f12f3
VS
620 if (m_resizing)
621 return;
622 m_resizing = TRUE;
623
624 int old_x = m_x;
625 int old_y = m_y;
626
627 int old_width = m_width;
628 int old_height = m_height;
629
630 if ((sizeFlags & wxSIZE_ALLOW_MINUS_ONE) == 0)
631 {
632 if (x != -1) m_x = x;
633 if (y != -1) m_y = y;
634 if (width != -1) m_width = width;
635 if (height != -1) m_height = height;
636 }
637 else
638 {
639 m_x = x;
640 m_y = y;
641 m_width = width;
642 m_height = height;
643 }
644
645/*
646 if ((sizeFlags & wxSIZE_AUTO_WIDTH) == wxSIZE_AUTO_WIDTH)
647 {
648 if (width == -1) m_width = 80;
649 }
650
651 if ((sizeFlags & wxSIZE_AUTO_HEIGHT) == wxSIZE_AUTO_HEIGHT)
652 {
653 if (height == -1) m_height = 26;
654 }
655*/
656
e7dda1ff
VS
657 int minWidth = GetMinWidth(),
658 minHeight = GetMinHeight(),
659 maxWidth = GetMaxWidth(),
660 maxHeight = GetMaxHeight();
661
662 if ((minWidth != -1) && (m_width < minWidth)) m_width = minWidth;
663 if ((minHeight != -1) && (m_height < minHeight)) m_height = minHeight;
664 if ((maxWidth != -1) && (m_width > maxWidth)) m_width = maxWidth;
665 if ((maxHeight != -1) && (m_height > maxHeight)) m_height = maxHeight;
7d9f12f3
VS
666
667 if ((m_x != -1) || (m_y != -1))
668 {
669 if ((m_x != old_x) || (m_y != old_y))
670 {
671 gtk_widget_set_uposition( m_widget, m_x, m_y );
672 }
673 }
674
675 if ((m_width != old_width) || (m_height != old_height))
676 {
e1f14d22
RR
677 if (m_widget->window)
678 gdk_window_resize( m_widget->window, m_width, m_height );
679 else
680 gtk_window_set_default_size( GTK_WINDOW(m_widget), m_width, m_height );
7d9f12f3
VS
681
682 /* we set the size in GtkOnSize, i.e. mostly the actual resizing is
683 done either directly before the frame is shown or in idle time
684 so that different calls to SetSize() don't lead to flicker. */
685 m_sizeSet = FALSE;
686 }
687
688 m_resizing = FALSE;
689}
690
691void wxTopLevelWindowGTK::DoGetClientSize( int *width, int *height ) const
692{
693 wxASSERT_MSG( (m_widget != NULL), wxT("invalid frame") );
694
695 wxWindow::DoGetClientSize( width, height );
696 if (height)
697 {
e1f14d22 698 // mini edge
7d9f12f3
VS
699 *height -= m_miniEdge*2 + m_miniTitle;
700 }
701 if (width)
702 {
703 *width -= m_miniEdge*2;
704 }
705}
706
707void wxTopLevelWindowGTK::DoSetClientSize( int width, int height )
708{
709 wxASSERT_MSG( (m_widget != NULL), wxT("invalid frame") );
710
82c9f85c 711 DoSetSize(-1, -1,
7d9f12f3
VS
712 width + m_miniEdge*2, height + m_miniEdge*2 + m_miniTitle, 0);
713}
714
715void wxTopLevelWindowGTK::GtkOnSize( int WXUNUSED(x), int WXUNUSED(y),
82c9f85c 716 int width, int height )
7d9f12f3
VS
717{
718 // due to a bug in gtk, x,y are always 0
719 // m_x = x;
720 // m_y = y;
721
e1f14d22 722 // avoid recursions
7d9f12f3
VS
723 if (m_resizing) return;
724 m_resizing = TRUE;
725
726 if ( m_wxwindow == NULL ) return;
727
728 m_width = width;
729 m_height = height;
730
0d53fc34 731 /* wxMDIChildFrame derives from wxFrame but it _is_ a wxWindow as it uses
7d9f12f3 732 wxWindow::Create to create it's GTK equivalent. m_mainWidget is only
0d53fc34 733 set in wxFrame::Create so it is used to check what kind of frame we
7d9f12f3
VS
734 have here. if m_mainWidget is NULL it is a wxMDIChildFrame and so we
735 skip the part which handles m_frameMenuBar, m_frameToolBar and (most
736 importantly) m_mainWidget */
737
e7dda1ff
VS
738 int minWidth = GetMinWidth(),
739 minHeight = GetMinHeight(),
740 maxWidth = GetMaxWidth(),
741 maxHeight = GetMaxHeight();
742
743 if ((minWidth != -1) && (m_width < minWidth)) m_width = minWidth;
744 if ((minHeight != -1) && (m_height < minHeight)) m_height = minHeight;
745 if ((maxWidth != -1) && (m_width > maxWidth)) m_width = maxWidth;
746 if ((maxHeight != -1) && (m_height > maxHeight)) m_height = maxHeight;
7d9f12f3
VS
747
748 if (m_mainWidget)
749 {
e1f14d22 750 // set size hints
7d9f12f3 751 gint flag = 0; // GDK_HINT_POS;
e7dda1ff
VS
752 if ((minWidth != -1) || (minHeight != -1)) flag |= GDK_HINT_MIN_SIZE;
753 if ((maxWidth != -1) || (maxHeight != -1)) flag |= GDK_HINT_MAX_SIZE;
7d9f12f3 754 GdkGeometry geom;
e7dda1ff
VS
755 geom.min_width = minWidth;
756 geom.min_height = minHeight;
757 geom.max_width = maxWidth;
758 geom.max_height = maxHeight;
7d9f12f3
VS
759 gtk_window_set_geometry_hints( GTK_WINDOW(m_widget),
760 (GtkWidget*) NULL,
761 &geom,
762 (GdkWindowHints) flag );
763
764 /* I revert back to wxGTK's original behaviour. m_mainWidget holds the
765 * menubar, the toolbar and the client area, which is represented by
766 * m_wxwindow.
767 * this hurts in the eye, but I don't want to call SetSize()
768 * because I don't want to call any non-native functions here. */
769
770 int client_x = m_miniEdge;
771 int client_y = m_miniEdge + m_miniTitle;
772 int client_w = m_width - 2*m_miniEdge;
773 int client_h = m_height - 2*m_miniEdge - m_miniTitle;
774 gtk_pizza_set_size( GTK_PIZZA(m_mainWidget),
775 m_wxwindow,
776 client_x, client_y, client_w, client_h );
777 }
778 else
779 {
e1f14d22
RR
780 // If there is no m_mainWidget between m_widget and m_wxwindow there
781 // is no need to set the size or position of m_wxwindow.
7d9f12f3
VS
782 }
783
784 m_sizeSet = TRUE;
785
786 // send size event to frame
787 wxSizeEvent event( wxSize(m_width,m_height), GetId() );
788 event.SetEventObject( this );
789 GetEventHandler()->ProcessEvent( event );
790
791 m_resizing = FALSE;
792}
793
794void wxTopLevelWindowGTK::OnInternalIdle()
795{
796 if (!m_sizeSet && GTK_WIDGET_REALIZED(m_wxwindow))
797 {
798 GtkOnSize( m_x, m_y, m_width, m_height );
799
800 // we'll come back later
801 if (g_isIdle)
802 wxapp_install_idle_handler();
803 return;
804 }
805
806 wxWindow::OnInternalIdle();
807}
808
809
810// ----------------------------------------------------------------------------
811// frame title/icon
812// ----------------------------------------------------------------------------
813
814void wxTopLevelWindowGTK::SetTitle( const wxString &title )
815{
816 wxASSERT_MSG( (m_widget != NULL), wxT("invalid frame") );
817
818 m_title = title;
819 gtk_window_set_title( GTK_WINDOW(m_widget), title.mbc_str() );
820}
821
f618020a 822void wxTopLevelWindowGTK::DoSetIcon( const wxIcon &icon )
7d9f12f3 823{
f618020a 824 if ( !icon.Ok() )
7d9f12f3
VS
825 return;
826
827 if (!m_widget->window)
828 return;
829
830 wxMask *mask = icon.GetMask();
831 GdkBitmap *bm = (GdkBitmap *) NULL;
832 if (mask) bm = mask->GetBitmap();
833
834 gdk_window_set_icon( m_widget->window, (GdkWindow *) NULL, icon.GetPixmap(), bm );
835}
836
f618020a
MB
837void wxTopLevelWindowGTK::SetIcon( const wxIcon &icon )
838{
839 SetIcons( wxIconBundle( icon ) );
840}
841
842void wxTopLevelWindowGTK::SetIcons( const wxIconBundle &icons )
843{
844 wxASSERT_MSG( (m_widget != NULL), wxT("invalid frame") );
845 GdkWindow* window = m_widget->window;
f618020a
MB
846
847 wxTopLevelWindowBase::SetIcons( icons );
848
849 DoSetIcon( icons.GetIcon( -1 ) );
7efaed4d
MB
850 if( window )
851 wxSetIconsX11( (WXDisplay*)GDK_WINDOW_XDISPLAY( window ),
852 (WXWindow)GDK_WINDOW_XWINDOW( window ), icons );
f618020a
MB
853}
854
7d9f12f3
VS
855// ----------------------------------------------------------------------------
856// frame state: maximized/iconized/normal
857// ----------------------------------------------------------------------------
858
859void wxTopLevelWindowGTK::Maximize(bool WXUNUSED(maximize))
860{
861 wxFAIL_MSG( _T("not implemented") );
862}
863
864bool wxTopLevelWindowGTK::IsMaximized() const
865{
866 // wxFAIL_MSG( _T("not implemented") );
867
868 // This is an approximation
869 return FALSE;
870}
871
872void wxTopLevelWindowGTK::Restore()
873{
874 wxFAIL_MSG( _T("not implemented") );
875}
876
877void wxTopLevelWindowGTK::Iconize( bool iconize )
878{
879 if (iconize)
880 {
881 GdkWindow *window = m_widget->window;
882
883 // you should do it later, for example from OnCreate() handler
884 wxCHECK_RET( window, _T("frame not created yet - can't iconize") );
885
886 XIconifyWindow( GDK_WINDOW_XDISPLAY( window ),
887 GDK_WINDOW_XWINDOW( window ),
888 DefaultScreen( GDK_DISPLAY() ) );
889 }
890}
891
892bool wxTopLevelWindowGTK::IsIconized() const
893{
894 return m_isIconized;
895}
896
897void wxTopLevelWindowGTK::SetIconizeState(bool iconize)
898{
899 if ( iconize != m_isIconized )
900 {
901 m_isIconized = iconize;
902 (void)SendIconizeEvent(iconize);
903 }
904}
905