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() );
140 wxLogTrace(wxT("activate"), wxT("Activating frame %p (from focus_in)"), g_activeFrame
);
141 wxActivateEvent
event(wxEVT_ACTIVATE
, FALSE
, g_activeFrame
->GetId());
142 event
.SetEventObject(g_activeFrame
);
143 g_activeFrame
->GetEventHandler()->ProcessEvent(event
);
145 g_activeFrame
= NULL
;
151 //-----------------------------------------------------------------------------
152 // "focus" from m_window
153 //-----------------------------------------------------------------------------
155 static gint
gtk_frame_focus_callback( GtkWidget
*widget
, GtkDirectionType
WXUNUSED(d
), wxWindow
*WXUNUSED(win
) )
158 wxapp_install_idle_handler();
160 // This disables GTK's tab traversal
161 gtk_signal_emit_stop_by_name( GTK_OBJECT(widget
), "focus" );
165 //-----------------------------------------------------------------------------
167 //-----------------------------------------------------------------------------
169 static void gtk_frame_size_callback( GtkWidget
*WXUNUSED(widget
), GtkAllocation
* alloc
, wxTopLevelWindowGTK
*win
)
172 wxapp_install_idle_handler();
177 if ((win
->m_width
!= alloc
->width
) || (win
->m_height
!= alloc
->height
))
180 wxPrintf( "OnSize from " );
181 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
182 wxPrintf( win->GetClassInfo()->GetClassName() );
183 wxPrintf( " %d %d %d %d\n", (int)alloc->x,
186 (int)alloc->height );
189 win
->m_width
= alloc
->width
;
190 win
->m_height
= alloc
->height
;
191 win
->GtkUpdateSize();
195 //-----------------------------------------------------------------------------
197 //-----------------------------------------------------------------------------
199 static gint
gtk_frame_delete_callback( GtkWidget
*WXUNUSED(widget
), GdkEvent
*WXUNUSED(event
), wxTopLevelWindowGTK
*win
)
202 wxapp_install_idle_handler();
204 if (win
->IsEnabled() &&
205 (g_openDialogs
== 0 || (win
->GetExtraStyle() & wxTOPLEVEL_EX_DIALOG
) ||
213 //-----------------------------------------------------------------------------
215 //-----------------------------------------------------------------------------
218 gtk_frame_configure_callback( GtkWidget
*WXUNUSED(widget
), GdkEventConfigure
*WXUNUSED(event
), wxTopLevelWindowGTK
*win
)
221 wxapp_install_idle_handler();
223 if (!win
->m_hasVMT
|| !win
->IsShown())
228 gdk_window_get_root_origin( win
->m_widget
->window
, &x
, &y
);
232 wxMoveEvent
mevent( wxPoint(win
->m_x
,win
->m_y
), win
->GetId() );
233 mevent
.SetEventObject( win
);
234 win
->GetEventHandler()->ProcessEvent( mevent
);
239 //-----------------------------------------------------------------------------
240 // "realize" from m_widget
241 //-----------------------------------------------------------------------------
243 // we cannot MWM hints and icons before the widget has been realized,
244 // so we do this directly after realization
247 gtk_frame_realized_callback( GtkWidget
* WXUNUSED(widget
),
248 wxTopLevelWindowGTK
*win
)
251 wxapp_install_idle_handler();
253 // All this is for Motif Window Manager "hints" and is supposed to be
254 // recognized by other WM as well. Not tested.
255 gdk_window_set_decorations(win
->m_widget
->window
,
256 (GdkWMDecoration
)win
->m_gdkDecor
);
257 gdk_window_set_functions(win
->m_widget
->window
,
258 (GdkWMFunction
)win
->m_gdkFunc
);
260 // GTK's shrinking/growing policy
261 if ((win
->m_gdkFunc
& GDK_FUNC_RESIZE
) == 0)
262 gtk_window_set_policy(GTK_WINDOW(win
->m_widget
), 0, 0, 1);
264 gtk_window_set_policy(GTK_WINDOW(win
->m_widget
), 1, 1, 1);
267 wxIconBundle iconsOld
= win
->GetIcons();
268 if ( iconsOld
.GetIcon(-1).Ok() )
270 win
->SetIcon( wxNullIcon
);
271 win
->SetIcons( iconsOld
);
275 //-----------------------------------------------------------------------------
276 // "map_event" from m_widget
277 //-----------------------------------------------------------------------------
280 gtk_frame_map_callback( GtkWidget
* WXUNUSED(widget
),
281 GdkEvent
* WXUNUSED(event
),
282 wxTopLevelWindow
*win
)
284 win
->SetIconizeState(FALSE
);
287 //-----------------------------------------------------------------------------
288 // "unmap_event" from m_widget
289 //-----------------------------------------------------------------------------
292 gtk_frame_unmap_callback( GtkWidget
* WXUNUSED(widget
),
293 GdkEvent
* WXUNUSED(event
),
294 wxTopLevelWindow
*win
)
296 win
->SetIconizeState(TRUE
);
299 //-----------------------------------------------------------------------------
300 // "expose_event" of m_client
301 //-----------------------------------------------------------------------------
303 static int gtk_window_expose_callback( GtkWidget
*widget
, GdkEventExpose
*gdk_event
, wxWindow
*win
)
305 GtkPizza
*pizza
= GTK_PIZZA(widget
);
307 gtk_paint_flat_box (win
->m_widget
->style
,
308 pizza
->bin_window
, GTK_STATE_NORMAL
,
318 //-----------------------------------------------------------------------------
319 // "draw" of m_client
320 //-----------------------------------------------------------------------------
324 static void gtk_window_draw_callback( GtkWidget
*widget
, GdkRectangle
*rect
, wxWindow
*win
)
326 GtkPizza
*pizza
= GTK_PIZZA(widget
);
328 gtk_paint_flat_box (win
->m_widget
->style
,
329 pizza
->bin_window
, GTK_STATE_NORMAL
,
339 // ----------------------------------------------------------------------------
340 // wxTopLevelWindowGTK itself
341 // ----------------------------------------------------------------------------
343 //-----------------------------------------------------------------------------
344 // InsertChild for wxTopLevelWindowGTK
345 //-----------------------------------------------------------------------------
347 /* Callback for wxTopLevelWindowGTK. This very strange beast has to be used because
348 * C++ has no virtual methods in a constructor. We have to emulate a
349 * virtual function here as wxWidgets requires different ways to insert
350 * a child in container classes. */
352 static void wxInsertChildInTopLevelWindow( wxTopLevelWindowGTK
* parent
, wxWindow
* child
)
354 wxASSERT( GTK_IS_WIDGET(child
->m_widget
) );
356 if (!parent
->m_insertInClientArea
)
358 // these are outside the client area
359 wxTopLevelWindowGTK
* frame
= (wxTopLevelWindowGTK
*) parent
;
360 gtk_pizza_put( GTK_PIZZA(frame
->m_mainWidget
),
361 GTK_WIDGET(child
->m_widget
),
369 // these are inside the client area
370 gtk_pizza_put( GTK_PIZZA(parent
->m_wxwindow
),
371 GTK_WIDGET(child
->m_widget
),
378 // resize on OnInternalIdle
379 parent
->GtkUpdateSize();
382 // ----------------------------------------------------------------------------
383 // wxTopLevelWindowGTK creation
384 // ----------------------------------------------------------------------------
386 void wxTopLevelWindowGTK::Init()
391 m_mainWidget
= (GtkWidget
*) NULL
;
392 m_insertInClientArea
= TRUE
;
393 m_isIconized
= FALSE
;
394 m_fsIsShowing
= FALSE
;
395 m_themeEnabled
= TRUE
;
396 m_gdkDecor
= m_gdkFunc
= 0;
400 bool wxTopLevelWindowGTK::Create( wxWindow
*parent
,
402 const wxString
& title
,
404 const wxSize
& sizeOrig
,
406 const wxString
&name
)
408 // always create a frame of some reasonable, even if arbitrary, size (at
409 // least for MSW compatibility)
410 wxSize size
= sizeOrig
;
411 size
.x
= WidthDefault(size
.x
);
412 size
.y
= HeightDefault(size
.y
);
414 wxTopLevelWindows
.Append( this );
416 m_needParent
= FALSE
;
418 if (!PreCreation( parent
, pos
, size
) ||
419 !CreateBase( parent
, id
, pos
, size
, style
, wxDefaultValidator
, name
))
421 wxFAIL_MSG( wxT("wxTopLevelWindowGTK creation failed") );
427 m_insertCallback
= (wxInsertChildFunction
) wxInsertChildInTopLevelWindow
;
429 // NB: m_widget may be !=NULL if it was created by derived class' Create,
430 // e.g. in wxTaskBarIconAreaGTK
431 if (m_widget
== NULL
)
433 GtkWindowType win_type
= GTK_WINDOW_TOPLEVEL
;
434 if (style
& wxFRAME_TOOL_WINDOW
)
435 win_type
= GTK_WINDOW_POPUP
;
437 if (GetExtraStyle() & wxTOPLEVEL_EX_DIALOG
)
440 m_widget
= gtk_window_new(GTK_WINDOW_TOPLEVEL
);
441 // Tell WM that this is a dialog window and make it center
442 // on parent by default (this is what GtkDialog ctor does):
443 gtk_window_set_type_hint(GTK_WINDOW(m_widget
),
444 GDK_WINDOW_TYPE_HINT_DIALOG
);
445 gtk_window_set_position(GTK_WINDOW(m_widget
),
446 GTK_WIN_POS_CENTER_ON_PARENT
);
448 m_widget
= gtk_window_new(GTK_WINDOW_DIALOG
);
453 m_widget
= gtk_window_new(win_type
);
457 wxWindow
*topParent
= wxGetTopLevelParent(m_parent
);
458 if (topParent
&& (((GTK_IS_WINDOW(topParent
->m_widget
)) &&
459 (GetExtraStyle() & wxTOPLEVEL_EX_DIALOG
)) ||
460 (style
& wxFRAME_FLOAT_ON_PARENT
)))
462 gtk_window_set_transient_for( GTK_WINDOW(m_widget
),
463 GTK_WINDOW(topParent
->m_widget
) );
466 #if GTK_CHECK_VERSION(2,2,0)
467 if (style
& wxFRAME_NO_TASKBAR
)
469 gtk_window_set_skip_taskbar_hint(GTK_WINDOW(m_widget
), TRUE
);
474 gtk_window_set_wmclass( GTK_WINDOW(m_widget
), wxGTK_CONV( name
), wxGTK_CONV( name
) );
476 gtk_window_set_title( GTK_WINDOW(m_widget
), wxGTK_CONV( title
) );
477 GTK_WIDGET_UNSET_FLAGS( m_widget
, GTK_CAN_FOCUS
);
479 gtk_signal_connect( GTK_OBJECT(m_widget
), "delete_event",
480 GTK_SIGNAL_FUNC(gtk_frame_delete_callback
), (gpointer
)this );
482 // m_mainWidget holds the toolbar, the menubar and the client area
483 m_mainWidget
= gtk_pizza_new();
484 gtk_widget_show( m_mainWidget
);
485 GTK_WIDGET_UNSET_FLAGS( m_mainWidget
, GTK_CAN_FOCUS
);
486 gtk_container_add( GTK_CONTAINER(m_widget
), m_mainWidget
);
488 if (m_miniEdge
== 0) // wxMiniFrame has its own version.
490 // For m_mainWidget themes
491 gtk_signal_connect( GTK_OBJECT(m_mainWidget
), "expose_event",
492 GTK_SIGNAL_FUNC(gtk_window_expose_callback
), (gpointer
)this );
494 gtk_signal_connect( GTK_OBJECT(m_mainWidget
), "draw",
495 GTK_SIGNAL_FUNC(gtk_window_draw_callback
), (gpointer
)this );
499 // m_wxwindow only represents the client area without toolbar and menubar
500 m_wxwindow
= gtk_pizza_new();
501 gtk_widget_show( m_wxwindow
);
502 gtk_container_add( GTK_CONTAINER(m_mainWidget
), m_wxwindow
);
504 // we donm't allow the frame to get the focus as otherwise
505 // the frame will grab it at arbitrary focus changes
506 GTK_WIDGET_UNSET_FLAGS( m_wxwindow
, GTK_CAN_FOCUS
);
508 if (m_parent
) m_parent
->AddChild( this );
510 // the user resized the frame by dragging etc.
511 gtk_signal_connect( GTK_OBJECT(m_widget
), "size_allocate",
512 GTK_SIGNAL_FUNC(gtk_frame_size_callback
), (gpointer
)this );
516 if ((m_x
!= -1) || (m_y
!= -1))
517 gtk_widget_set_uposition( m_widget
, m_x
, m_y
);
519 gtk_window_set_default_size( GTK_WINDOW(m_widget
), m_width
, m_height
);
521 // we cannot set MWM hints and icons before the widget has
522 // been realized, so we do this directly after realization
523 gtk_signal_connect( GTK_OBJECT(m_widget
), "realize",
524 GTK_SIGNAL_FUNC(gtk_frame_realized_callback
), (gpointer
) this );
526 // the only way to get the window size is to connect to this event
527 gtk_signal_connect( GTK_OBJECT(m_widget
), "configure_event",
528 GTK_SIGNAL_FUNC(gtk_frame_configure_callback
), (gpointer
)this );
530 // map and unmap for iconized state
531 gtk_signal_connect( GTK_OBJECT(m_widget
), "map_event",
532 GTK_SIGNAL_FUNC(gtk_frame_map_callback
), (gpointer
)this );
533 gtk_signal_connect( GTK_OBJECT(m_widget
), "unmap_event",
534 GTK_SIGNAL_FUNC(gtk_frame_unmap_callback
), (gpointer
)this );
536 // the only way to get the window size is to connect to this event
537 gtk_signal_connect( GTK_OBJECT(m_widget
), "configure_event",
538 GTK_SIGNAL_FUNC(gtk_frame_configure_callback
), (gpointer
)this );
540 // disable native tab traversal
541 gtk_signal_connect( GTK_OBJECT(m_widget
), "focus",
542 GTK_SIGNAL_FUNC(gtk_frame_focus_callback
), (gpointer
)this );
545 gtk_signal_connect( GTK_OBJECT(m_widget
), "focus_in_event",
546 GTK_SIGNAL_FUNC(gtk_frame_focus_in_callback
), (gpointer
)this );
547 gtk_signal_connect( GTK_OBJECT(m_widget
), "focus_out_event",
548 GTK_SIGNAL_FUNC(gtk_frame_focus_out_callback
), (gpointer
)this );
551 if ((m_miniEdge
> 0) || (style
& wxSIMPLE_BORDER
) || (style
& wxNO_BORDER
))
558 m_gdkDecor
= (long) GDK_DECOR_BORDER
;
559 m_gdkFunc
= (long) GDK_FUNC_MOVE
;
561 // All this is for Motif Window Manager "hints" and is supposed to be
562 // recognized by other WMs as well.
563 if ((style
& wxCAPTION
) != 0)
565 m_gdkDecor
|= GDK_DECOR_TITLE
;
567 if ((style
& wxCLOSE_BOX
) != 0)
569 m_gdkFunc
|= GDK_FUNC_CLOSE
;
571 if ((style
& wxSYSTEM_MENU
) != 0)
573 m_gdkDecor
|= GDK_DECOR_MENU
;
575 if ((style
& wxMINIMIZE_BOX
) != 0)
577 m_gdkFunc
|= GDK_FUNC_MINIMIZE
;
578 m_gdkDecor
|= GDK_DECOR_MINIMIZE
;
580 if ((style
& wxMAXIMIZE_BOX
) != 0)
582 m_gdkFunc
|= GDK_FUNC_MAXIMIZE
;
583 m_gdkDecor
|= GDK_DECOR_MAXIMIZE
;
585 if ((style
& wxRESIZE_BORDER
) != 0)
587 m_gdkFunc
|= GDK_FUNC_RESIZE
;
588 m_gdkDecor
|= GDK_DECOR_RESIZEH
;
595 wxTopLevelWindowGTK::~wxTopLevelWindowGTK()
599 wxASSERT_MSG( FALSE
, _T("Window still grabbed"));
603 m_isBeingDeleted
= TRUE
;
605 // it may also be GtkScrolledWindow in the case of an MDI child
606 if (GTK_IS_WINDOW(m_widget
))
608 gtk_window_set_focus( GTK_WINDOW(m_widget
), NULL
);
611 if (g_activeFrame
== this)
612 g_activeFrame
= NULL
;
613 if (g_lastActiveFrame
== this)
614 g_lastActiveFrame
= NULL
;
619 bool wxTopLevelWindowGTK::ShowFullScreen(bool show
, long style
)
621 if (show
== m_fsIsShowing
) return FALSE
; // return what?
623 m_fsIsShowing
= show
;
625 GdkWindow
*window
= m_widget
->window
;
626 wxX11FullScreenMethod method
=
627 wxGetFullScreenMethodX11((WXDisplay
*)GDK_DISPLAY(),
628 (WXWindow
)GDK_ROOT_WINDOW());
632 m_fsSaveFlag
= style
;
633 GetPosition( &m_fsSaveFrame
.x
, &m_fsSaveFrame
.y
);
634 GetSize( &m_fsSaveFrame
.width
, &m_fsSaveFrame
.height
);
636 int screen_width
,screen_height
;
637 wxDisplaySize( &screen_width
, &screen_height
);
639 gint client_x
, client_y
, root_x
, root_y
;
642 if (method
!= wxX11_FS_WMSPEC
)
644 // don't do it always, Metacity hates it
645 m_fsSaveGdkFunc
= m_gdkFunc
;
646 m_fsSaveGdkDecor
= m_gdkDecor
;
647 m_gdkFunc
= m_gdkDecor
= 0;
648 gdk_window_set_decorations(window
, (GdkWMDecoration
)0);
649 gdk_window_set_functions(window
, (GdkWMFunction
)0);
652 gdk_window_get_origin (m_widget
->window
, &root_x
, &root_y
);
653 gdk_window_get_geometry (m_widget
->window
, &client_x
, &client_y
,
654 &width
, &height
, NULL
);
656 gdk_window_move_resize (m_widget
->window
, -client_x
, -client_y
,
657 screen_width
+ 1, screen_height
+ 1);
659 wxSetFullScreenStateX11((WXDisplay
*)GDK_DISPLAY(),
660 (WXWindow
)GDK_ROOT_WINDOW(),
661 (WXWindow
)GDK_WINDOW_XWINDOW(window
),
662 show
, &m_fsSaveFrame
, method
);
666 if (method
!= wxX11_FS_WMSPEC
)
668 // don't do it always, Metacity hates it
669 m_gdkFunc
= m_fsSaveGdkFunc
;
670 m_gdkDecor
= m_fsSaveGdkDecor
;
671 gdk_window_set_decorations(window
, (GdkWMDecoration
)m_gdkDecor
);
672 gdk_window_set_functions(window
, (GdkWMFunction
)m_gdkFunc
);
675 wxSetFullScreenStateX11((WXDisplay
*)GDK_DISPLAY(),
676 (WXWindow
)GDK_ROOT_WINDOW(),
677 (WXWindow
)GDK_WINDOW_XWINDOW(window
),
678 show
, &m_fsSaveFrame
, method
);
680 SetSize(m_fsSaveFrame
.x
, m_fsSaveFrame
.y
,
681 m_fsSaveFrame
.width
, m_fsSaveFrame
.height
);
688 // ----------------------------------------------------------------------------
689 // overridden wxWindow methods
690 // ----------------------------------------------------------------------------
692 bool wxTopLevelWindowGTK::Show( bool show
)
694 wxASSERT_MSG( (m_widget
!= NULL
), wxT("invalid frame") );
696 if (show
&& !m_sizeSet
)
698 /* by calling GtkOnSize here, we don't have to call
699 either after showing the frame, which would entail
700 much ugly flicker or from within the size_allocate
701 handler, because GTK 1.1.X forbids that. */
703 GtkOnSize( m_x
, m_y
, m_width
, m_height
);
706 return wxWindow::Show( show
);
709 void wxTopLevelWindowGTK::DoMoveWindow(int WXUNUSED(x
), int WXUNUSED(y
), int WXUNUSED(width
), int WXUNUSED(height
) )
711 wxFAIL_MSG( wxT("DoMoveWindow called for wxTopLevelWindowGTK") );
714 void wxTopLevelWindowGTK::DoSetSize( int x
, int y
, int width
, int height
, int sizeFlags
)
716 wxASSERT_MSG( (m_widget
!= NULL
), wxT("invalid frame") );
718 // this shouldn't happen: wxFrame, wxMDIParentFrame and wxMDIChildFrame have m_wxwindow
719 wxASSERT_MSG( (m_wxwindow
!= NULL
), wxT("invalid frame") );
729 int old_width
= m_width
;
730 int old_height
= m_height
;
732 if ((sizeFlags
& wxSIZE_ALLOW_MINUS_ONE
) == 0)
734 if (x
!= -1) m_x
= x
;
735 if (y
!= -1) m_y
= y
;
742 if (width
!= -1) m_width
= width
;
743 if (height
!= -1) m_height
= height
;
746 if ((sizeFlags & wxSIZE_AUTO_WIDTH) == wxSIZE_AUTO_WIDTH)
748 if (width == -1) m_width = 80;
751 if ((sizeFlags & wxSIZE_AUTO_HEIGHT) == wxSIZE_AUTO_HEIGHT)
753 if (height == -1) m_height = 26;
757 int minWidth
= GetMinWidth(),
758 minHeight
= GetMinHeight(),
759 maxWidth
= GetMaxWidth(),
760 maxHeight
= GetMaxHeight();
763 // GPE's window manager doesn't like size hints
764 // at all, esp. when the user has to use the
772 if ((minWidth
!= -1) && (m_width
< minWidth
)) m_width
= minWidth
;
773 if ((minHeight
!= -1) && (m_height
< minHeight
)) m_height
= minHeight
;
774 if ((maxWidth
!= -1) && (m_width
> maxWidth
)) m_width
= maxWidth
;
775 if ((maxHeight
!= -1) && (m_height
> maxHeight
)) m_height
= maxHeight
;
777 if ((m_x
!= -1) || (m_y
!= -1))
779 if ((m_x
!= old_x
) || (m_y
!= old_y
))
781 gtk_widget_set_uposition( m_widget
, m_x
, m_y
);
785 if ((m_width
!= old_width
) || (m_height
!= old_height
))
787 if (m_widget
->window
)
788 gdk_window_resize( m_widget
->window
, m_width
, m_height
);
790 gtk_window_set_default_size( GTK_WINDOW(m_widget
), m_width
, m_height
);
792 /* we set the size in GtkOnSize, i.e. mostly the actual resizing is
793 done either directly before the frame is shown or in idle time
794 so that different calls to SetSize() don't lead to flicker. */
801 void wxTopLevelWindowGTK::DoGetClientSize( int *width
, int *height
) const
803 wxASSERT_MSG( (m_widget
!= NULL
), wxT("invalid frame") );
805 wxWindow::DoGetClientSize( width
, height
);
809 *height
-= m_miniEdge
*2 + m_miniTitle
;
813 *width
-= m_miniEdge
*2;
817 void wxTopLevelWindowGTK::DoSetClientSize( int width
, int height
)
819 wxASSERT_MSG( (m_widget
!= NULL
), wxT("invalid frame") );
822 width
+ m_miniEdge
*2, height
+ m_miniEdge
*2 + m_miniTitle
, 0);
825 void wxTopLevelWindowGTK::GtkOnSize( int WXUNUSED(x
), int WXUNUSED(y
),
826 int width
, int height
)
828 // due to a bug in gtk, x,y are always 0
833 if (m_resizing
) return;
836 if ( m_wxwindow
== NULL
) return;
841 /* wxMDIChildFrame derives from wxFrame but it _is_ a wxWindow as it uses
842 wxWindow::Create to create it's GTK equivalent. m_mainWidget is only
843 set in wxFrame::Create so it is used to check what kind of frame we
844 have here. if m_mainWidget is NULL it is a wxMDIChildFrame and so we
845 skip the part which handles m_frameMenuBar, m_frameToolBar and (most
846 importantly) m_mainWidget */
848 int minWidth
= GetMinWidth(),
849 minHeight
= GetMinHeight(),
850 maxWidth
= GetMaxWidth(),
851 maxHeight
= GetMaxHeight();
854 // GPE's window manager doesn't like size hints
855 // at all, esp. when the user has to use the
863 if ((minWidth
!= -1) && (m_width
< minWidth
)) m_width
= minWidth
;
864 if ((minHeight
!= -1) && (m_height
< minHeight
)) m_height
= minHeight
;
865 if ((maxWidth
!= -1) && (m_width
> maxWidth
)) m_width
= maxWidth
;
866 if ((maxHeight
!= -1) && (m_height
> maxHeight
)) m_height
= maxHeight
;
871 gint flag
= 0; // GDK_HINT_POS;
874 if ((minWidth
!= -1) || (minHeight
!= -1)) flag
|= GDK_HINT_MIN_SIZE
;
875 if ((maxWidth
!= -1) || (maxHeight
!= -1)) flag
|= GDK_HINT_MAX_SIZE
;
877 geom
.min_width
= minWidth
;
878 geom
.min_height
= minHeight
;
880 // Because of the way we set GDK_HINT_MAX_SIZE above, if either of
881 // maxHeight or maxWidth is set, we must set them both, else the
882 // remaining -1 will be taken literally.
884 // I'm certain this also happens elsewhere, and is the probable
885 // cause of other such things as:
886 // Gtk-WARNING **: gtk_widget_size_allocate():
887 // attempt to allocate widget with width 65535 and height 600
888 // but I don't have time to track them all now..
890 // Really we need to encapulate all this height/width business and
891 // stop any old method from ripping at the members directly and
892 // scattering -1's without regard for who might resolve them later.
894 geom
.max_width
= ( maxHeight
== -1 ) ? maxWidth
895 : ( maxWidth
== -1 ) ? wxGetDisplaySize().GetWidth()
898 geom
.max_height
= ( maxWidth
== -1 ) ? maxHeight
// ( == -1 here )
899 : ( maxHeight
== -1 ) ? wxGetDisplaySize().GetHeight()
902 gtk_window_set_geometry_hints( GTK_WINDOW(m_widget
),
905 (GdkWindowHints
) flag
);
907 /* I revert back to wxGTK's original behaviour. m_mainWidget holds the
908 * menubar, the toolbar and the client area, which is represented by
910 * this hurts in the eye, but I don't want to call SetSize()
911 * because I don't want to call any non-native functions here. */
913 int client_x
= m_miniEdge
;
914 int client_y
= m_miniEdge
+ m_miniTitle
;
915 int client_w
= m_width
- 2*m_miniEdge
;
916 int client_h
= m_height
- 2*m_miniEdge
- m_miniTitle
;
918 gtk_pizza_set_size( GTK_PIZZA(m_mainWidget
),
920 client_x
, client_y
, client_w
, client_h
);
924 // If there is no m_mainWidget between m_widget and m_wxwindow there
925 // is no need to set the size or position of m_wxwindow.
930 // send size event to frame
931 wxSizeEvent
event( wxSize(m_width
,m_height
), GetId() );
932 event
.SetEventObject( this );
933 GetEventHandler()->ProcessEvent( event
);
938 void wxTopLevelWindowGTK::OnInternalIdle()
940 if (!m_sizeSet
&& GTK_WIDGET_REALIZED(m_wxwindow
))
942 GtkOnSize( m_x
, m_y
, m_width
, m_height
);
944 // we'll come back later
946 wxapp_install_idle_handler();
950 // set the focus if not done yet and if we can already do it
951 if ( GTK_WIDGET_REALIZED(m_wxwindow
) )
953 if ( g_delayedFocus
&&
954 wxGetTopLevelParent((wxWindow
*)g_delayedFocus
) == this )
956 wxLogTrace(_T("focus"),
957 _T("Setting focus from wxTLW::OnIdle() to %s(%s)"),
958 g_delayedFocus
->GetClassInfo()->GetClassName(),
959 g_delayedFocus
->GetLabel().c_str());
961 g_delayedFocus
->SetFocus();
962 g_delayedFocus
= NULL
;
966 wxWindow::OnInternalIdle();
968 // Synthetize activate events.
969 if ( g_sendActivateEvent
!= -1 )
971 bool activate
= g_sendActivateEvent
!= 0;
973 // if (!activate) wxPrintf( wxT("de") );
974 // wxPrintf( wxT("activate\n") );
977 g_sendActivateEvent
= -1;
979 wxTheApp
->SetActive(activate
, (wxWindow
*)g_lastActiveFrame
);
983 // ----------------------------------------------------------------------------
985 // ----------------------------------------------------------------------------
987 void wxTopLevelWindowGTK::SetTitle( const wxString
&title
)
989 wxASSERT_MSG( (m_widget
!= NULL
), wxT("invalid frame") );
992 gtk_window_set_title( GTK_WINDOW(m_widget
), wxGTK_CONV( title
) );
995 void wxTopLevelWindowGTK::SetIcon( const wxIcon
&icon
)
997 SetIcons( wxIconBundle( icon
) );
1000 void wxTopLevelWindowGTK::SetIcons( const wxIconBundle
&icons
)
1002 wxASSERT_MSG( (m_widget
!= NULL
), wxT("invalid frame") );
1004 wxTopLevelWindowBase::SetIcons( icons
);
1008 size_t max
= icons
.m_icons
.GetCount();
1010 for (size_t i
= 0; i
< max
; i
++)
1012 if (icons
.m_icons
[i
].Ok())
1014 list
= g_list_prepend(list
, icons
.m_icons
[i
].GetPixbuf());
1017 gtk_window_set_icon_list(GTK_WINDOW(m_widget
), list
);
1020 #else // !__WXGTK20__
1021 GdkWindow
* window
= m_widget
->window
;
1025 wxIcon icon
= icons
.GetIcon(-1);
1028 wxMask
*mask
= icon
.GetMask();
1029 GdkBitmap
*bm
= (GdkBitmap
*) NULL
;
1030 if (mask
) bm
= mask
->GetBitmap();
1032 gdk_window_set_icon( m_widget
->window
, (GdkWindow
*) NULL
, icon
.GetPixmap(), bm
);
1035 wxSetIconsX11( (WXDisplay
*)GDK_WINDOW_XDISPLAY( window
),
1036 (WXWindow
)GDK_WINDOW_XWINDOW( window
), icons
);
1037 #endif // !__WXGTK20__
1040 // ----------------------------------------------------------------------------
1041 // frame state: maximized/iconized/normal
1042 // ----------------------------------------------------------------------------
1044 void wxTopLevelWindowGTK::Maximize(bool maximize
)
1048 gtk_window_maximize( GTK_WINDOW( m_widget
) );
1050 gtk_window_unmaximize( GTK_WINDOW( m_widget
) );
1052 wxFAIL_MSG( _T("not implemented") );
1056 bool wxTopLevelWindowGTK::IsMaximized() const
1059 if(!m_widget
->window
)
1062 return gdk_window_get_state(m_widget
->window
) & GDK_WINDOW_STATE_MAXIMIZED
;
1064 // wxFAIL_MSG( _T("not implemented") );
1066 // This is an approximation
1071 void wxTopLevelWindowGTK::Restore()
1074 // "Present" seems similar enough to "restore"
1075 gtk_window_present( GTK_WINDOW( m_widget
) );
1077 wxFAIL_MSG( _T("not implemented") );
1081 void wxTopLevelWindowGTK::Iconize( bool iconize
)
1085 gtk_window_iconify( GTK_WINDOW( m_widget
) );
1087 gtk_window_deiconify( GTK_WINDOW( m_widget
) );
1091 GdkWindow
*window
= m_widget
->window
;
1093 // you should do it later, for example from OnCreate() handler
1094 wxCHECK_RET( window
, _T("frame not created yet - can't iconize") );
1096 XIconifyWindow( GDK_WINDOW_XDISPLAY( window
),
1097 GDK_WINDOW_XWINDOW( window
),
1098 DefaultScreen( GDK_DISPLAY() ) );
1103 bool wxTopLevelWindowGTK::IsIconized() const
1105 return m_isIconized
;
1108 void wxTopLevelWindowGTK::SetIconizeState(bool iconize
)
1110 if ( iconize
!= m_isIconized
)
1112 m_isIconized
= iconize
;
1113 (void)SendIconizeEvent(iconize
);
1117 void wxTopLevelWindowGTK::AddGrab()
1122 gtk_grab_add( m_widget
);
1124 gtk_grab_remove( m_widget
);
1128 void wxTopLevelWindowGTK::RemoveGrab()
1139 static bool do_shape_combine_region(GdkWindow
* window
, const wxRegion
& region
)
1143 if (region
.IsEmpty())
1145 gdk_window_shape_combine_mask(window
, NULL
, 0, 0);
1150 gdk_window_shape_combine_region(window
, region
.GetRegion(), 0, 0);
1152 wxBitmap bmp
= region
.ConvertToBitmap();
1153 bmp
.SetMask(new wxMask(bmp
, *wxBLACK
));
1154 GdkBitmap
* mask
= bmp
.GetMask()->GetBitmap();
1155 gdk_window_shape_combine_mask(window
, mask
, 0, 0);
1164 bool wxTopLevelWindowGTK::SetShape(const wxRegion
& region
)
1166 wxCHECK_MSG( HasFlag(wxFRAME_SHAPED
), FALSE
,
1167 _T("Shaped windows must be created with the wxFRAME_SHAPED style."));
1169 GdkWindow
*window
= NULL
;
1172 window
= GTK_PIZZA(m_wxwindow
)->bin_window
;
1173 do_shape_combine_region(window
, region
);
1175 window
= m_widget
->window
;
1176 return do_shape_combine_region(window
, region
);
1179 bool wxTopLevelWindowGTK::IsActive()
1181 return (this == (wxTopLevelWindowGTK
*)g_activeFrame
);