1 /////////////////////////////////////////////////////////////////////////////
4 // Author: Robert Roebling
6 // Copyright: (c) 1998 Robert Roebling
7 // Licence: wxWindows licence
8 /////////////////////////////////////////////////////////////////////////////
10 // ============================================================================
12 // ============================================================================
14 // ----------------------------------------------------------------------------
16 // ----------------------------------------------------------------------------
18 #if defined(__GNUG__) && !defined(NO_GCC_PRAGMA)
19 #pragma implementation "toplevel.h"
22 // For compilers that support precompilation, includes "wx.h".
23 #include "wx/wxprec.h"
26 #define XIconifyWindow XICONIFYWINDOW
32 #include "wx/dialog.h"
33 #include "wx/control.h"
35 #include "wx/dcclient.h"
36 #include "wx/gtk/private.h"
38 #include "wx/settings.h"
43 #include <gdk/gdkkeysyms.h>
46 #include "wx/gtk/win_gtk.h"
48 #include "wx/unix/utilsx11.h"
51 #include <X11/Xatom.h>
53 // ----------------------------------------------------------------------------
55 // ----------------------------------------------------------------------------
57 extern void wxapp_install_idle_handler();
60 // ----------------------------------------------------------------------------
62 // ----------------------------------------------------------------------------
64 extern wxList wxPendingDelete
;
66 extern int g_openDialogs
;
67 extern wxWindowGTK
*g_delayedFocus
;
69 // the frame that is currently active (i.e. its child has focus). It is
70 // used to generate wxActivateEvents
71 static wxTopLevelWindowGTK
*g_activeFrame
= (wxTopLevelWindowGTK
*) NULL
;
72 static wxTopLevelWindowGTK
*g_lastActiveFrame
= (wxTopLevelWindowGTK
*) NULL
;
74 // if we detect that the app has got/lost the focus, we set this variable to
75 // either TRUE or FALSE and an activate event will be sent during the next
76 // OnIdle() call and it is reset to -1: this value means that we shouldn't
77 // send any activate events at all
78 static int g_sendActivateEvent
= -1;
80 //-----------------------------------------------------------------------------
82 //-----------------------------------------------------------------------------
84 static gint
gtk_frame_focus_in_callback( GtkWidget
*widget
,
85 GdkEvent
*WXUNUSED(event
),
86 wxTopLevelWindowGTK
*win
)
89 wxapp_install_idle_handler();
91 switch ( g_sendActivateEvent
)
94 // we've got focus from outside, synthetize wxActivateEvent
95 g_sendActivateEvent
= 1;
99 // another our window just lost focus, it was already ours before
100 // - don't send any wxActivateEvent
101 g_sendActivateEvent
= -1;
106 g_lastActiveFrame
= g_activeFrame
;
108 // wxPrintf( wxT("active: %s\n"), win->GetTitle().c_str() );
110 wxLogTrace(wxT("activate"), wxT("Activating frame %p (from focus_in)"), g_activeFrame
);
111 wxActivateEvent
event(wxEVT_ACTIVATE
, TRUE
, g_activeFrame
->GetId());
112 event
.SetEventObject(g_activeFrame
);
113 g_activeFrame
->GetEventHandler()->ProcessEvent(event
);
118 //-----------------------------------------------------------------------------
120 //-----------------------------------------------------------------------------
122 static gint
gtk_frame_focus_out_callback( GtkWidget
*widget
,
123 GdkEventFocus
*WXUNUSED(gdk_event
),
124 wxTopLevelWindowGTK
*win
)
127 wxapp_install_idle_handler();
129 // if the focus goes out of our app alltogether, OnIdle() will send
130 // wxActivateEvent, otherwise gtk_window_focus_in_callback() will reset
131 // g_sendActivateEvent to -1
132 g_sendActivateEvent
= 0;
134 // wxASSERT_MSG( (g_activeFrame == win), wxT("TLW deactivatd although it wasn't active") );
136 // wxPrintf( wxT("inactive: %s\n"), win->GetTitle().c_str() );
138 wxLogTrace(wxT("activate"), wxT("Activating frame %p (from focus_in)"), g_activeFrame
);
139 wxActivateEvent
event(wxEVT_ACTIVATE
, FALSE
, g_activeFrame
->GetId());
140 event
.SetEventObject(g_activeFrame
);
141 g_activeFrame
->GetEventHandler()->ProcessEvent(event
);
143 g_activeFrame
= NULL
;
148 //-----------------------------------------------------------------------------
149 // "focus" from m_window
150 //-----------------------------------------------------------------------------
152 static gint
gtk_frame_focus_callback( GtkWidget
*widget
, GtkDirectionType
WXUNUSED(d
), wxWindow
*WXUNUSED(win
) )
155 wxapp_install_idle_handler();
157 // This disables GTK's tab traversal
158 gtk_signal_emit_stop_by_name( GTK_OBJECT(widget
), "focus" );
162 //-----------------------------------------------------------------------------
164 //-----------------------------------------------------------------------------
166 static void gtk_frame_size_callback( GtkWidget
*WXUNUSED(widget
), GtkAllocation
* alloc
, wxTopLevelWindowGTK
*win
)
169 wxapp_install_idle_handler();
174 if ((win
->m_width
!= alloc
->width
) || (win
->m_height
!= alloc
->height
))
177 wxPrintf( "OnSize from " );
178 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
179 wxPrintf( win->GetClassInfo()->GetClassName() );
180 wxPrintf( " %d %d %d %d\n", (int)alloc->x,
183 (int)alloc->height );
186 win
->m_width
= alloc
->width
;
187 win
->m_height
= alloc
->height
;
188 win
->GtkUpdateSize();
192 //-----------------------------------------------------------------------------
194 //-----------------------------------------------------------------------------
196 static gint
gtk_frame_delete_callback( GtkWidget
*WXUNUSED(widget
), GdkEvent
*WXUNUSED(event
), wxTopLevelWindowGTK
*win
)
199 wxapp_install_idle_handler();
201 if (win
->IsEnabled() &&
202 (g_openDialogs
== 0 || (win
->GetExtraStyle() & wxTOPLEVEL_EX_DIALOG
) ||
210 //-----------------------------------------------------------------------------
212 //-----------------------------------------------------------------------------
215 gtk_frame_configure_callback( GtkWidget
*WXUNUSED(widget
), GdkEventConfigure
*WXUNUSED(event
), wxTopLevelWindowGTK
*win
)
218 wxapp_install_idle_handler();
220 if (!win
->m_hasVMT
|| !win
->IsShown())
225 gdk_window_get_root_origin( win
->m_widget
->window
, &x
, &y
);
229 wxMoveEvent
mevent( wxPoint(win
->m_x
,win
->m_y
), win
->GetId() );
230 mevent
.SetEventObject( win
);
231 win
->GetEventHandler()->ProcessEvent( mevent
);
236 //-----------------------------------------------------------------------------
237 // "realize" from m_widget
238 //-----------------------------------------------------------------------------
240 // we cannot MWM hints and icons before the widget has been realized,
241 // so we do this directly after realization
244 gtk_frame_realized_callback( GtkWidget
* WXUNUSED(widget
),
245 wxTopLevelWindowGTK
*win
)
248 wxapp_install_idle_handler();
250 // All this is for Motif Window Manager "hints" and is supposed to be
251 // recognized by other WM as well. Not tested.
252 gdk_window_set_decorations(win
->m_widget
->window
,
253 (GdkWMDecoration
)win
->m_gdkDecor
);
254 gdk_window_set_functions(win
->m_widget
->window
,
255 (GdkWMFunction
)win
->m_gdkFunc
);
257 // GTK's shrinking/growing policy
258 if ((win
->m_gdkFunc
& GDK_FUNC_RESIZE
) == 0)
259 gtk_window_set_policy(GTK_WINDOW(win
->m_widget
), 0, 0, 1);
261 gtk_window_set_policy(GTK_WINDOW(win
->m_widget
), 1, 1, 1);
264 wxIconBundle iconsOld
= win
->GetIcons();
265 if ( iconsOld
.GetIcon(-1).Ok() )
267 win
->SetIcon( wxNullIcon
);
268 win
->SetIcons( iconsOld
);
272 //-----------------------------------------------------------------------------
273 // "map_event" from m_widget
274 //-----------------------------------------------------------------------------
277 gtk_frame_map_callback( GtkWidget
* WXUNUSED(widget
),
278 GdkEvent
* WXUNUSED(event
),
279 wxTopLevelWindow
*win
)
281 win
->SetIconizeState(FALSE
);
284 //-----------------------------------------------------------------------------
285 // "unmap_event" from m_widget
286 //-----------------------------------------------------------------------------
289 gtk_frame_unmap_callback( GtkWidget
* WXUNUSED(widget
),
290 GdkEvent
* WXUNUSED(event
),
291 wxTopLevelWindow
*win
)
293 win
->SetIconizeState(TRUE
);
296 //-----------------------------------------------------------------------------
297 // "expose_event" of m_client
298 //-----------------------------------------------------------------------------
300 static int gtk_window_expose_callback( GtkWidget
*widget
, GdkEventExpose
*gdk_event
, wxWindow
*win
)
302 GtkPizza
*pizza
= GTK_PIZZA(widget
);
304 gtk_paint_flat_box (win
->m_widget
->style
,
305 pizza
->bin_window
, GTK_STATE_NORMAL
,
315 //-----------------------------------------------------------------------------
316 // "draw" of m_client
317 //-----------------------------------------------------------------------------
321 static void gtk_window_draw_callback( GtkWidget
*widget
, GdkRectangle
*rect
, wxWindow
*win
)
323 GtkPizza
*pizza
= GTK_PIZZA(widget
);
325 gtk_paint_flat_box (win
->m_widget
->style
,
326 pizza
->bin_window
, GTK_STATE_NORMAL
,
336 // ----------------------------------------------------------------------------
337 // wxTopLevelWindowGTK itself
338 // ----------------------------------------------------------------------------
340 //-----------------------------------------------------------------------------
341 // InsertChild for wxTopLevelWindowGTK
342 //-----------------------------------------------------------------------------
344 /* Callback for wxTopLevelWindowGTK. This very strange beast has to be used because
345 * C++ has no virtual methods in a constructor. We have to emulate a
346 * virtual function here as wxWidgets requires different ways to insert
347 * a child in container classes. */
349 static void wxInsertChildInTopLevelWindow( wxTopLevelWindowGTK
* parent
, wxWindow
* child
)
351 wxASSERT( GTK_IS_WIDGET(child
->m_widget
) );
353 if (!parent
->m_insertInClientArea
)
355 // these are outside the client area
356 wxTopLevelWindowGTK
* frame
= (wxTopLevelWindowGTK
*) parent
;
357 gtk_pizza_put( GTK_PIZZA(frame
->m_mainWidget
),
358 GTK_WIDGET(child
->m_widget
),
366 // these are inside the client area
367 gtk_pizza_put( GTK_PIZZA(parent
->m_wxwindow
),
368 GTK_WIDGET(child
->m_widget
),
375 // resize on OnInternalIdle
376 parent
->GtkUpdateSize();
379 // ----------------------------------------------------------------------------
380 // wxTopLevelWindowGTK creation
381 // ----------------------------------------------------------------------------
383 void wxTopLevelWindowGTK::Init()
388 m_mainWidget
= (GtkWidget
*) NULL
;
389 m_insertInClientArea
= TRUE
;
390 m_isIconized
= FALSE
;
391 m_fsIsShowing
= FALSE
;
392 m_themeEnabled
= TRUE
;
393 m_gdkDecor
= m_gdkFunc
= 0;
397 bool wxTopLevelWindowGTK::Create( wxWindow
*parent
,
399 const wxString
& title
,
401 const wxSize
& sizeOrig
,
403 const wxString
&name
)
405 // always create a frame of some reasonable, even if arbitrary, size (at
406 // least for MSW compatibility)
407 wxSize size
= sizeOrig
;
408 size
.x
= WidthDefault(size
.x
);
409 size
.y
= HeightDefault(size
.y
);
411 wxTopLevelWindows
.Append( this );
413 m_needParent
= FALSE
;
415 if (!PreCreation( parent
, pos
, size
) ||
416 !CreateBase( parent
, id
, pos
, size
, style
, wxDefaultValidator
, name
))
418 wxFAIL_MSG( wxT("wxTopLevelWindowGTK creation failed") );
424 m_insertCallback
= (wxInsertChildFunction
) wxInsertChildInTopLevelWindow
;
426 // NB: m_widget may be !=NULL if it was created by derived class' Create,
427 // e.g. in wxTaskBarIconAreaGTK
428 if (m_widget
== NULL
)
430 GtkWindowType win_type
= GTK_WINDOW_TOPLEVEL
;
431 if (style
& wxFRAME_TOOL_WINDOW
)
432 win_type
= GTK_WINDOW_POPUP
;
434 if (GetExtraStyle() & wxTOPLEVEL_EX_DIALOG
)
437 m_widget
= gtk_window_new(GTK_WINDOW_TOPLEVEL
);
438 // Tell WM that this is a dialog window and make it center
439 // on parent by default (this is what GtkDialog ctor does):
440 gtk_window_set_type_hint(GTK_WINDOW(m_widget
),
441 GDK_WINDOW_TYPE_HINT_DIALOG
);
442 gtk_window_set_position(GTK_WINDOW(m_widget
),
443 GTK_WIN_POS_CENTER_ON_PARENT
);
445 m_widget
= gtk_window_new(GTK_WINDOW_DIALOG
);
450 m_widget
= gtk_window_new(win_type
);
454 if (m_parent
&& (((GTK_IS_WINDOW(m_parent
->m_widget
)) &&
455 (GetExtraStyle() & wxTOPLEVEL_EX_DIALOG
)) ||
456 (style
& wxFRAME_FLOAT_ON_PARENT
)))
458 gtk_window_set_transient_for( GTK_WINDOW(m_widget
), GTK_WINDOW(m_parent
->m_widget
) );
461 #if GTK_CHECK_VERSION(2,2,0)
462 if (style
& wxFRAME_NO_TASKBAR
)
464 gtk_window_set_skip_taskbar_hint(GTK_WINDOW(m_widget
), TRUE
);
469 gtk_window_set_wmclass( GTK_WINDOW(m_widget
), wxGTK_CONV( name
), wxGTK_CONV( name
) );
471 gtk_window_set_title( GTK_WINDOW(m_widget
), wxGTK_CONV( title
) );
472 GTK_WIDGET_UNSET_FLAGS( m_widget
, GTK_CAN_FOCUS
);
474 gtk_signal_connect( GTK_OBJECT(m_widget
), "delete_event",
475 GTK_SIGNAL_FUNC(gtk_frame_delete_callback
), (gpointer
)this );
477 // m_mainWidget holds the toolbar, the menubar and the client area
478 m_mainWidget
= gtk_pizza_new();
479 gtk_widget_show( m_mainWidget
);
480 GTK_WIDGET_UNSET_FLAGS( m_mainWidget
, GTK_CAN_FOCUS
);
481 gtk_container_add( GTK_CONTAINER(m_widget
), m_mainWidget
);
483 if (m_miniEdge
== 0) // wxMiniFrame has its own version.
485 // For m_mainWidget themes
486 gtk_signal_connect( GTK_OBJECT(m_mainWidget
), "expose_event",
487 GTK_SIGNAL_FUNC(gtk_window_expose_callback
), (gpointer
)this );
489 gtk_signal_connect( GTK_OBJECT(m_mainWidget
), "draw",
490 GTK_SIGNAL_FUNC(gtk_window_draw_callback
), (gpointer
)this );
494 // m_wxwindow only represents the client area without toolbar and menubar
495 m_wxwindow
= gtk_pizza_new();
496 gtk_widget_show( m_wxwindow
);
497 gtk_container_add( GTK_CONTAINER(m_mainWidget
), m_wxwindow
);
499 // we donm't allow the frame to get the focus as otherwise
500 // the frame will grab it at arbitrary focus changes
501 GTK_WIDGET_UNSET_FLAGS( m_wxwindow
, GTK_CAN_FOCUS
);
503 if (m_parent
) m_parent
->AddChild( this );
505 // the user resized the frame by dragging etc.
506 gtk_signal_connect( GTK_OBJECT(m_widget
), "size_allocate",
507 GTK_SIGNAL_FUNC(gtk_frame_size_callback
), (gpointer
)this );
511 if ((m_x
!= -1) || (m_y
!= -1))
512 gtk_widget_set_uposition( m_widget
, m_x
, m_y
);
514 gtk_window_set_default_size( GTK_WINDOW(m_widget
), m_width
, m_height
);
516 // we cannot set MWM hints and icons before the widget has
517 // been realized, so we do this directly after realization
518 gtk_signal_connect( GTK_OBJECT(m_widget
), "realize",
519 GTK_SIGNAL_FUNC(gtk_frame_realized_callback
), (gpointer
) this );
521 // the only way to get the window size is to connect to this event
522 gtk_signal_connect( GTK_OBJECT(m_widget
), "configure_event",
523 GTK_SIGNAL_FUNC(gtk_frame_configure_callback
), (gpointer
)this );
525 // map and unmap for iconized state
526 gtk_signal_connect( GTK_OBJECT(m_widget
), "map_event",
527 GTK_SIGNAL_FUNC(gtk_frame_map_callback
), (gpointer
)this );
528 gtk_signal_connect( GTK_OBJECT(m_widget
), "unmap_event",
529 GTK_SIGNAL_FUNC(gtk_frame_unmap_callback
), (gpointer
)this );
531 // the only way to get the window size is to connect to this event
532 gtk_signal_connect( GTK_OBJECT(m_widget
), "configure_event",
533 GTK_SIGNAL_FUNC(gtk_frame_configure_callback
), (gpointer
)this );
535 // disable native tab traversal
536 gtk_signal_connect( GTK_OBJECT(m_widget
), "focus",
537 GTK_SIGNAL_FUNC(gtk_frame_focus_callback
), (gpointer
)this );
540 gtk_signal_connect( GTK_OBJECT(m_widget
), "focus_in_event",
541 GTK_SIGNAL_FUNC(gtk_frame_focus_in_callback
), (gpointer
)this );
542 gtk_signal_connect( GTK_OBJECT(m_widget
), "focus_out_event",
543 GTK_SIGNAL_FUNC(gtk_frame_focus_out_callback
), (gpointer
)this );
546 if ((m_miniEdge
> 0) || (style
& wxSIMPLE_BORDER
) || (style
& wxNO_BORDER
))
553 m_gdkDecor
= (long) GDK_DECOR_BORDER
;
554 m_gdkFunc
= (long) GDK_FUNC_MOVE
;
556 // All this is for Motif Window Manager "hints" and is supposed to be
557 // recognized by other WMs as well.
558 if ((style
& wxCAPTION
) != 0)
560 m_gdkDecor
|= GDK_DECOR_TITLE
;
562 if ((style
& wxCLOSE_BOX
) != 0)
564 m_gdkFunc
|= GDK_FUNC_CLOSE
;
566 if ((style
& wxSYSTEM_MENU
) != 0)
568 m_gdkDecor
|= GDK_DECOR_MENU
;
570 if ((style
& wxMINIMIZE_BOX
) != 0)
572 m_gdkFunc
|= GDK_FUNC_MINIMIZE
;
573 m_gdkDecor
|= GDK_DECOR_MINIMIZE
;
575 if ((style
& wxMAXIMIZE_BOX
) != 0)
577 m_gdkFunc
|= GDK_FUNC_MAXIMIZE
;
578 m_gdkDecor
|= GDK_DECOR_MAXIMIZE
;
580 if ((style
& wxRESIZE_BORDER
) != 0)
582 m_gdkFunc
|= GDK_FUNC_RESIZE
;
583 m_gdkDecor
|= GDK_DECOR_RESIZEH
;
590 wxTopLevelWindowGTK::~wxTopLevelWindowGTK()
594 wxASSERT_MSG( FALSE
, _T("Window still grabbed"));
598 m_isBeingDeleted
= TRUE
;
600 // it may also be GtkScrolledWindow in the case of an MDI child
601 if (GTK_IS_WINDOW(m_widget
))
603 gtk_window_set_focus( GTK_WINDOW(m_widget
), NULL
);
606 if (g_activeFrame
== this)
607 g_activeFrame
= NULL
;
608 if (g_lastActiveFrame
== this)
609 g_lastActiveFrame
= NULL
;
614 bool wxTopLevelWindowGTK::ShowFullScreen(bool show
, long style
)
616 if (show
== m_fsIsShowing
) return FALSE
; // return what?
618 m_fsIsShowing
= show
;
620 GdkWindow
*window
= m_widget
->window
;
621 wxX11FullScreenMethod method
=
622 wxGetFullScreenMethodX11((WXDisplay
*)GDK_DISPLAY(),
623 (WXWindow
)GDK_ROOT_WINDOW());
627 m_fsSaveFlag
= style
;
628 GetPosition( &m_fsSaveFrame
.x
, &m_fsSaveFrame
.y
);
629 GetSize( &m_fsSaveFrame
.width
, &m_fsSaveFrame
.height
);
631 int screen_width
,screen_height
;
632 wxDisplaySize( &screen_width
, &screen_height
);
634 gint client_x
, client_y
, root_x
, root_y
;
637 if (method
!= wxX11_FS_WMSPEC
)
639 // don't do it always, Metacity hates it
640 m_fsSaveGdkFunc
= m_gdkFunc
;
641 m_fsSaveGdkDecor
= m_gdkDecor
;
642 m_gdkFunc
= m_gdkDecor
= 0;
643 gdk_window_set_decorations(window
, (GdkWMDecoration
)0);
644 gdk_window_set_functions(window
, (GdkWMFunction
)0);
647 gdk_window_get_origin (m_widget
->window
, &root_x
, &root_y
);
648 gdk_window_get_geometry (m_widget
->window
, &client_x
, &client_y
,
649 &width
, &height
, NULL
);
651 gdk_window_move_resize (m_widget
->window
, -client_x
, -client_y
,
652 screen_width
+ 1, screen_height
+ 1);
654 wxSetFullScreenStateX11((WXDisplay
*)GDK_DISPLAY(),
655 (WXWindow
)GDK_ROOT_WINDOW(),
656 (WXWindow
)GDK_WINDOW_XWINDOW(window
),
657 show
, &m_fsSaveFrame
, method
);
661 if (method
!= wxX11_FS_WMSPEC
)
663 // don't do it always, Metacity hates it
664 m_gdkFunc
= m_fsSaveGdkFunc
;
665 m_gdkDecor
= m_fsSaveGdkDecor
;
666 gdk_window_set_decorations(window
, (GdkWMDecoration
)m_gdkDecor
);
667 gdk_window_set_functions(window
, (GdkWMFunction
)m_gdkFunc
);
670 wxSetFullScreenStateX11((WXDisplay
*)GDK_DISPLAY(),
671 (WXWindow
)GDK_ROOT_WINDOW(),
672 (WXWindow
)GDK_WINDOW_XWINDOW(window
),
673 show
, &m_fsSaveFrame
, method
);
675 SetSize(m_fsSaveFrame
.x
, m_fsSaveFrame
.y
,
676 m_fsSaveFrame
.width
, m_fsSaveFrame
.height
);
683 // ----------------------------------------------------------------------------
684 // overridden wxWindow methods
685 // ----------------------------------------------------------------------------
687 bool wxTopLevelWindowGTK::Show( bool show
)
689 wxASSERT_MSG( (m_widget
!= NULL
), wxT("invalid frame") );
691 if (show
&& !m_sizeSet
)
693 /* by calling GtkOnSize here, we don't have to call
694 either after showing the frame, which would entail
695 much ugly flicker or from within the size_allocate
696 handler, because GTK 1.1.X forbids that. */
698 GtkOnSize( m_x
, m_y
, m_width
, m_height
);
701 return wxWindow::Show( show
);
704 void wxTopLevelWindowGTK::DoMoveWindow(int WXUNUSED(x
), int WXUNUSED(y
), int WXUNUSED(width
), int WXUNUSED(height
) )
706 wxFAIL_MSG( wxT("DoMoveWindow called for wxTopLevelWindowGTK") );
709 void wxTopLevelWindowGTK::DoSetSize( int x
, int y
, int width
, int height
, int sizeFlags
)
711 wxASSERT_MSG( (m_widget
!= NULL
), wxT("invalid frame") );
713 // this shouldn't happen: wxFrame, wxMDIParentFrame and wxMDIChildFrame have m_wxwindow
714 wxASSERT_MSG( (m_wxwindow
!= NULL
), wxT("invalid frame") );
724 int old_width
= m_width
;
725 int old_height
= m_height
;
727 if ((sizeFlags
& wxSIZE_ALLOW_MINUS_ONE
) == 0)
729 if (x
!= -1) m_x
= x
;
730 if (y
!= -1) m_y
= y
;
737 if (width
!= -1) m_width
= width
;
738 if (height
!= -1) m_height
= height
;
741 if ((sizeFlags & wxSIZE_AUTO_WIDTH) == wxSIZE_AUTO_WIDTH)
743 if (width == -1) m_width = 80;
746 if ((sizeFlags & wxSIZE_AUTO_HEIGHT) == wxSIZE_AUTO_HEIGHT)
748 if (height == -1) m_height = 26;
752 int minWidth
= GetMinWidth(),
753 minHeight
= GetMinHeight(),
754 maxWidth
= GetMaxWidth(),
755 maxHeight
= GetMaxHeight();
758 // GPE's window manager doesn't like size hints
759 // at all, esp. when the user has to use the
767 if ((minWidth
!= -1) && (m_width
< minWidth
)) m_width
= minWidth
;
768 if ((minHeight
!= -1) && (m_height
< minHeight
)) m_height
= minHeight
;
769 if ((maxWidth
!= -1) && (m_width
> maxWidth
)) m_width
= maxWidth
;
770 if ((maxHeight
!= -1) && (m_height
> maxHeight
)) m_height
= maxHeight
;
772 if ((m_x
!= -1) || (m_y
!= -1))
774 if ((m_x
!= old_x
) || (m_y
!= old_y
))
776 gtk_widget_set_uposition( m_widget
, m_x
, m_y
);
780 if ((m_width
!= old_width
) || (m_height
!= old_height
))
782 if (m_widget
->window
)
783 gdk_window_resize( m_widget
->window
, m_width
, m_height
);
785 gtk_window_set_default_size( GTK_WINDOW(m_widget
), m_width
, m_height
);
787 /* we set the size in GtkOnSize, i.e. mostly the actual resizing is
788 done either directly before the frame is shown or in idle time
789 so that different calls to SetSize() don't lead to flicker. */
796 void wxTopLevelWindowGTK::DoGetClientSize( int *width
, int *height
) const
798 wxASSERT_MSG( (m_widget
!= NULL
), wxT("invalid frame") );
800 wxWindow::DoGetClientSize( width
, height
);
804 *height
-= m_miniEdge
*2 + m_miniTitle
;
808 *width
-= m_miniEdge
*2;
812 void wxTopLevelWindowGTK::DoSetClientSize( int width
, int height
)
814 wxASSERT_MSG( (m_widget
!= NULL
), wxT("invalid frame") );
817 width
+ m_miniEdge
*2, height
+ m_miniEdge
*2 + m_miniTitle
, 0);
820 void wxTopLevelWindowGTK::GtkOnSize( int WXUNUSED(x
), int WXUNUSED(y
),
821 int width
, int height
)
823 // due to a bug in gtk, x,y are always 0
828 if (m_resizing
) return;
831 if ( m_wxwindow
== NULL
) return;
836 /* wxMDIChildFrame derives from wxFrame but it _is_ a wxWindow as it uses
837 wxWindow::Create to create it's GTK equivalent. m_mainWidget is only
838 set in wxFrame::Create so it is used to check what kind of frame we
839 have here. if m_mainWidget is NULL it is a wxMDIChildFrame and so we
840 skip the part which handles m_frameMenuBar, m_frameToolBar and (most
841 importantly) m_mainWidget */
843 int minWidth
= GetMinWidth(),
844 minHeight
= GetMinHeight(),
845 maxWidth
= GetMaxWidth(),
846 maxHeight
= GetMaxHeight();
849 // GPE's window manager doesn't like size hints
850 // at all, esp. when the user has to use the
858 if ((minWidth
!= -1) && (m_width
< minWidth
)) m_width
= minWidth
;
859 if ((minHeight
!= -1) && (m_height
< minHeight
)) m_height
= minHeight
;
860 if ((maxWidth
!= -1) && (m_width
> maxWidth
)) m_width
= maxWidth
;
861 if ((maxHeight
!= -1) && (m_height
> maxHeight
)) m_height
= maxHeight
;
866 gint flag
= 0; // GDK_HINT_POS;
869 if ((minWidth
!= -1) || (minHeight
!= -1)) flag
|= GDK_HINT_MIN_SIZE
;
870 if ((maxWidth
!= -1) || (maxHeight
!= -1)) flag
|= GDK_HINT_MAX_SIZE
;
872 geom
.min_width
= minWidth
;
873 geom
.min_height
= minHeight
;
875 // Because of the way we set GDK_HINT_MAX_SIZE above, if either of
876 // maxHeight or maxWidth is set, we must set them both, else the
877 // remaining -1 will be taken literally.
879 // I'm certain this also happens elsewhere, and is the probable
880 // cause of other such things as:
881 // Gtk-WARNING **: gtk_widget_size_allocate():
882 // attempt to allocate widget with width 65535 and height 600
883 // but I don't have time to track them all now..
885 // Really we need to encapulate all this height/width business and
886 // stop any old method from ripping at the members directly and
887 // scattering -1's without regard for who might resolve them later.
889 geom
.max_width
= ( maxHeight
== -1 ) ? maxWidth
890 : ( maxWidth
== -1 ) ? wxGetDisplaySize().GetWidth()
893 geom
.max_height
= ( maxWidth
== -1 ) ? maxHeight
// ( == -1 here )
894 : ( maxHeight
== -1 ) ? wxGetDisplaySize().GetHeight()
897 gtk_window_set_geometry_hints( GTK_WINDOW(m_widget
),
900 (GdkWindowHints
) flag
);
902 /* I revert back to wxGTK's original behaviour. m_mainWidget holds the
903 * menubar, the toolbar and the client area, which is represented by
905 * this hurts in the eye, but I don't want to call SetSize()
906 * because I don't want to call any non-native functions here. */
908 int client_x
= m_miniEdge
;
909 int client_y
= m_miniEdge
+ m_miniTitle
;
910 int client_w
= m_width
- 2*m_miniEdge
;
911 int client_h
= m_height
- 2*m_miniEdge
- m_miniTitle
;
913 gtk_pizza_set_size( GTK_PIZZA(m_mainWidget
),
915 client_x
, client_y
, client_w
, client_h
);
919 // If there is no m_mainWidget between m_widget and m_wxwindow there
920 // is no need to set the size or position of m_wxwindow.
925 // send size event to frame
926 wxSizeEvent
event( wxSize(m_width
,m_height
), GetId() );
927 event
.SetEventObject( this );
928 GetEventHandler()->ProcessEvent( event
);
933 void wxTopLevelWindowGTK::OnInternalIdle()
935 if (!m_sizeSet
&& GTK_WIDGET_REALIZED(m_wxwindow
))
937 GtkOnSize( m_x
, m_y
, m_width
, m_height
);
939 // we'll come back later
941 wxapp_install_idle_handler();
945 // set the focus if not done yet and if we can already do it
946 if ( GTK_WIDGET_REALIZED(m_wxwindow
) )
948 if ( g_delayedFocus
&&
949 wxGetTopLevelParent((wxWindow
*)g_delayedFocus
) == this )
951 wxLogTrace(_T("focus"),
952 _T("Setting focus from wxTLW::OnIdle() to %s(%s)"),
953 g_delayedFocus
->GetClassInfo()->GetClassName(),
954 g_delayedFocus
->GetLabel().c_str());
956 g_delayedFocus
->SetFocus();
957 g_delayedFocus
= NULL
;
961 wxWindow::OnInternalIdle();
963 // Synthetize activate events.
964 if ( g_sendActivateEvent
!= -1 )
966 bool activate
= g_sendActivateEvent
!= 0;
969 g_sendActivateEvent
= -1;
971 wxTheApp
->SetActive(activate
, (wxWindow
*)g_lastActiveFrame
);
975 // ----------------------------------------------------------------------------
977 // ----------------------------------------------------------------------------
979 void wxTopLevelWindowGTK::SetTitle( const wxString
&title
)
981 wxASSERT_MSG( (m_widget
!= NULL
), wxT("invalid frame") );
984 gtk_window_set_title( GTK_WINDOW(m_widget
), wxGTK_CONV( title
) );
987 void wxTopLevelWindowGTK::SetIcon( const wxIcon
&icon
)
989 SetIcons( wxIconBundle( icon
) );
992 void wxTopLevelWindowGTK::SetIcons( const wxIconBundle
&icons
)
994 wxASSERT_MSG( (m_widget
!= NULL
), wxT("invalid frame") );
996 wxTopLevelWindowBase::SetIcons( icons
);
1000 size_t max
= icons
.m_icons
.GetCount();
1002 for (size_t i
= 0; i
< max
; i
++)
1004 if (icons
.m_icons
[i
].Ok())
1006 list
= g_list_prepend(list
, icons
.m_icons
[i
].GetPixbuf());
1009 gtk_window_set_icon_list(GTK_WINDOW(m_widget
), list
);
1012 #else // !__WXGTK20__
1013 GdkWindow
* window
= m_widget
->window
;
1017 wxIcon icon
= icons
.GetIcon(-1);
1020 wxMask
*mask
= icon
.GetMask();
1021 GdkBitmap
*bm
= (GdkBitmap
*) NULL
;
1022 if (mask
) bm
= mask
->GetBitmap();
1024 gdk_window_set_icon( m_widget
->window
, (GdkWindow
*) NULL
, icon
.GetPixmap(), bm
);
1027 wxSetIconsX11( (WXDisplay
*)GDK_WINDOW_XDISPLAY( window
),
1028 (WXWindow
)GDK_WINDOW_XWINDOW( window
), icons
);
1029 #endif // !__WXGTK20__
1032 // ----------------------------------------------------------------------------
1033 // frame state: maximized/iconized/normal
1034 // ----------------------------------------------------------------------------
1036 void wxTopLevelWindowGTK::Maximize(bool maximize
)
1040 gtk_window_maximize( GTK_WINDOW( m_widget
) );
1042 gtk_window_unmaximize( GTK_WINDOW( m_widget
) );
1044 wxFAIL_MSG( _T("not implemented") );
1048 bool wxTopLevelWindowGTK::IsMaximized() const
1051 if(!m_widget
->window
)
1054 return gdk_window_get_state(m_widget
->window
) & GDK_WINDOW_STATE_MAXIMIZED
;
1056 // wxFAIL_MSG( _T("not implemented") );
1058 // This is an approximation
1063 void wxTopLevelWindowGTK::Restore()
1066 // "Present" seems similar enough to "restore"
1067 gtk_window_present( GTK_WINDOW( m_widget
) );
1069 wxFAIL_MSG( _T("not implemented") );
1073 void wxTopLevelWindowGTK::Iconize( bool iconize
)
1077 gtk_window_iconify( GTK_WINDOW( m_widget
) );
1079 gtk_window_deiconify( GTK_WINDOW( m_widget
) );
1083 GdkWindow
*window
= m_widget
->window
;
1085 // you should do it later, for example from OnCreate() handler
1086 wxCHECK_RET( window
, _T("frame not created yet - can't iconize") );
1088 XIconifyWindow( GDK_WINDOW_XDISPLAY( window
),
1089 GDK_WINDOW_XWINDOW( window
),
1090 DefaultScreen( GDK_DISPLAY() ) );
1095 bool wxTopLevelWindowGTK::IsIconized() const
1097 return m_isIconized
;
1100 void wxTopLevelWindowGTK::SetIconizeState(bool iconize
)
1102 if ( iconize
!= m_isIconized
)
1104 m_isIconized
= iconize
;
1105 (void)SendIconizeEvent(iconize
);
1109 void wxTopLevelWindowGTK::AddGrab()
1114 gtk_grab_add( m_widget
);
1116 gtk_grab_remove( m_widget
);
1120 void wxTopLevelWindowGTK::RemoveGrab()
1131 static bool do_shape_combine_region(GdkWindow
* window
, const wxRegion
& region
)
1135 if (region
.IsEmpty())
1137 gdk_window_shape_combine_mask(window
, NULL
, 0, 0);
1142 gdk_window_shape_combine_region(window
, region
.GetRegion(), 0, 0);
1144 wxBitmap bmp
= region
.ConvertToBitmap();
1145 bmp
.SetMask(new wxMask(bmp
, *wxBLACK
));
1146 GdkBitmap
* mask
= bmp
.GetMask()->GetBitmap();
1147 gdk_window_shape_combine_mask(window
, mask
, 0, 0);
1156 bool wxTopLevelWindowGTK::SetShape(const wxRegion
& region
)
1158 wxCHECK_MSG( HasFlag(wxFRAME_SHAPED
), FALSE
,
1159 _T("Shaped windows must be created with the wxFRAME_SHAPED style."));
1161 GdkWindow
*window
= NULL
;
1164 window
= GTK_PIZZA(m_wxwindow
)->bin_window
;
1165 do_shape_combine_region(window
, region
);
1167 window
= m_widget
->window
;
1168 return do_shape_combine_region(window
, region
);
1171 bool wxTopLevelWindowGTK::IsActive()
1173 return (this == (wxTopLevelWindowGTK
*)g_activeFrame
);