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 if (GetExtraStyle() & wxTOPLEVEL_EX_DIALOG
)
436 m_widget
= gtk_window_new(GTK_WINDOW_TOPLEVEL
);
437 // Tell WM that this is a dialog window and make it center
438 // on parent by default (this is what GtkDialog ctor does):
439 gtk_window_set_type_hint(GTK_WINDOW(m_widget
),
440 GDK_WINDOW_TYPE_HINT_DIALOG
);
441 gtk_window_set_position(GTK_WINDOW(m_widget
),
442 GTK_WIN_POS_CENTER_ON_PARENT
);
444 m_widget
= gtk_window_new(GTK_WINDOW_DIALOG
);
449 m_widget
= gtk_window_new(GTK_WINDOW_TOPLEVEL
);
451 if (style
& wxFRAME_TOOL_WINDOW
)
452 gtk_window_set_type_hint(GTK_WINDOW(m_widget
),
453 GDK_WINDOW_TYPE_HINT_UTILITY
);
459 wxWindow
*topParent
= wxGetTopLevelParent(m_parent
);
460 if (topParent
&& (((GTK_IS_WINDOW(topParent
->m_widget
)) &&
461 (GetExtraStyle() & wxTOPLEVEL_EX_DIALOG
)) ||
462 (style
& wxFRAME_FLOAT_ON_PARENT
)))
464 gtk_window_set_transient_for( GTK_WINDOW(m_widget
),
465 GTK_WINDOW(topParent
->m_widget
) );
468 #if GTK_CHECK_VERSION(2,2,0)
469 if (style
& wxFRAME_NO_TASKBAR
)
471 gtk_window_set_skip_taskbar_hint(GTK_WINDOW(m_widget
), TRUE
);
476 gtk_window_set_wmclass( GTK_WINDOW(m_widget
), wxGTK_CONV( name
), wxGTK_CONV( name
) );
478 gtk_window_set_title( GTK_WINDOW(m_widget
), wxGTK_CONV( title
) );
479 GTK_WIDGET_UNSET_FLAGS( m_widget
, GTK_CAN_FOCUS
);
481 gtk_signal_connect( GTK_OBJECT(m_widget
), "delete_event",
482 GTK_SIGNAL_FUNC(gtk_frame_delete_callback
), (gpointer
)this );
484 // m_mainWidget holds the toolbar, the menubar and the client area
485 m_mainWidget
= gtk_pizza_new();
486 gtk_widget_show( m_mainWidget
);
487 GTK_WIDGET_UNSET_FLAGS( m_mainWidget
, GTK_CAN_FOCUS
);
488 gtk_container_add( GTK_CONTAINER(m_widget
), m_mainWidget
);
490 if (m_miniEdge
== 0) // wxMiniFrame has its own version.
492 // For m_mainWidget themes
493 gtk_signal_connect( GTK_OBJECT(m_mainWidget
), "expose_event",
494 GTK_SIGNAL_FUNC(gtk_window_expose_callback
), (gpointer
)this );
496 gtk_signal_connect( GTK_OBJECT(m_mainWidget
), "draw",
497 GTK_SIGNAL_FUNC(gtk_window_draw_callback
), (gpointer
)this );
501 // m_wxwindow only represents the client area without toolbar and menubar
502 m_wxwindow
= gtk_pizza_new();
503 gtk_widget_show( m_wxwindow
);
504 gtk_container_add( GTK_CONTAINER(m_mainWidget
), m_wxwindow
);
506 // we donm't allow the frame to get the focus as otherwise
507 // the frame will grab it at arbitrary focus changes
508 GTK_WIDGET_UNSET_FLAGS( m_wxwindow
, GTK_CAN_FOCUS
);
510 if (m_parent
) m_parent
->AddChild( this );
512 // the user resized the frame by dragging etc.
513 gtk_signal_connect( GTK_OBJECT(m_widget
), "size_allocate",
514 GTK_SIGNAL_FUNC(gtk_frame_size_callback
), (gpointer
)this );
518 if ((m_x
!= -1) || (m_y
!= -1))
519 gtk_widget_set_uposition( m_widget
, m_x
, m_y
);
521 gtk_window_set_default_size( GTK_WINDOW(m_widget
), m_width
, m_height
);
523 // we cannot set MWM hints and icons before the widget has
524 // been realized, so we do this directly after realization
525 gtk_signal_connect( GTK_OBJECT(m_widget
), "realize",
526 GTK_SIGNAL_FUNC(gtk_frame_realized_callback
), (gpointer
) this );
528 // the only way to get the window size is to connect to this event
529 gtk_signal_connect( GTK_OBJECT(m_widget
), "configure_event",
530 GTK_SIGNAL_FUNC(gtk_frame_configure_callback
), (gpointer
)this );
532 // map and unmap for iconized state
533 gtk_signal_connect( GTK_OBJECT(m_widget
), "map_event",
534 GTK_SIGNAL_FUNC(gtk_frame_map_callback
), (gpointer
)this );
535 gtk_signal_connect( GTK_OBJECT(m_widget
), "unmap_event",
536 GTK_SIGNAL_FUNC(gtk_frame_unmap_callback
), (gpointer
)this );
538 // the only way to get the window size is to connect to this event
539 gtk_signal_connect( GTK_OBJECT(m_widget
), "configure_event",
540 GTK_SIGNAL_FUNC(gtk_frame_configure_callback
), (gpointer
)this );
542 // disable native tab traversal
543 gtk_signal_connect( GTK_OBJECT(m_widget
), "focus",
544 GTK_SIGNAL_FUNC(gtk_frame_focus_callback
), (gpointer
)this );
547 gtk_signal_connect( GTK_OBJECT(m_widget
), "focus_in_event",
548 GTK_SIGNAL_FUNC(gtk_frame_focus_in_callback
), (gpointer
)this );
549 gtk_signal_connect( GTK_OBJECT(m_widget
), "focus_out_event",
550 GTK_SIGNAL_FUNC(gtk_frame_focus_out_callback
), (gpointer
)this );
553 if ((m_miniEdge
> 0) || (style
& wxSIMPLE_BORDER
) || (style
& wxNO_BORDER
))
560 m_gdkDecor
= (long) GDK_DECOR_BORDER
;
561 m_gdkFunc
= (long) GDK_FUNC_MOVE
;
563 // All this is for Motif Window Manager "hints" and is supposed to be
564 // recognized by other WMs as well.
565 if ((style
& wxCAPTION
) != 0)
567 m_gdkDecor
|= GDK_DECOR_TITLE
;
569 if ((style
& wxCLOSE_BOX
) != 0)
571 m_gdkFunc
|= GDK_FUNC_CLOSE
;
573 if ((style
& wxSYSTEM_MENU
) != 0)
575 m_gdkDecor
|= GDK_DECOR_MENU
;
577 if ((style
& wxMINIMIZE_BOX
) != 0)
579 m_gdkFunc
|= GDK_FUNC_MINIMIZE
;
580 m_gdkDecor
|= GDK_DECOR_MINIMIZE
;
582 if ((style
& wxMAXIMIZE_BOX
) != 0)
584 m_gdkFunc
|= GDK_FUNC_MAXIMIZE
;
585 m_gdkDecor
|= GDK_DECOR_MAXIMIZE
;
587 if ((style
& wxRESIZE_BORDER
) != 0)
589 m_gdkFunc
|= GDK_FUNC_RESIZE
;
590 m_gdkDecor
|= GDK_DECOR_RESIZEH
;
597 wxTopLevelWindowGTK::~wxTopLevelWindowGTK()
601 wxASSERT_MSG( FALSE
, _T("Window still grabbed"));
605 m_isBeingDeleted
= TRUE
;
607 // it may also be GtkScrolledWindow in the case of an MDI child
608 if (GTK_IS_WINDOW(m_widget
))
610 gtk_window_set_focus( GTK_WINDOW(m_widget
), NULL
);
613 if (g_activeFrame
== this)
614 g_activeFrame
= NULL
;
615 if (g_lastActiveFrame
== this)
616 g_lastActiveFrame
= NULL
;
621 bool wxTopLevelWindowGTK::ShowFullScreen(bool show
, long style
)
623 if (show
== m_fsIsShowing
) return FALSE
; // return what?
625 m_fsIsShowing
= show
;
627 GdkWindow
*window
= m_widget
->window
;
628 wxX11FullScreenMethod method
=
629 wxGetFullScreenMethodX11((WXDisplay
*)GDK_DISPLAY(),
630 (WXWindow
)GDK_ROOT_WINDOW());
634 m_fsSaveFlag
= style
;
635 GetPosition( &m_fsSaveFrame
.x
, &m_fsSaveFrame
.y
);
636 GetSize( &m_fsSaveFrame
.width
, &m_fsSaveFrame
.height
);
638 int screen_width
,screen_height
;
639 wxDisplaySize( &screen_width
, &screen_height
);
641 gint client_x
, client_y
, root_x
, root_y
;
644 if (method
!= wxX11_FS_WMSPEC
)
646 // don't do it always, Metacity hates it
647 m_fsSaveGdkFunc
= m_gdkFunc
;
648 m_fsSaveGdkDecor
= m_gdkDecor
;
649 m_gdkFunc
= m_gdkDecor
= 0;
650 gdk_window_set_decorations(window
, (GdkWMDecoration
)0);
651 gdk_window_set_functions(window
, (GdkWMFunction
)0);
654 gdk_window_get_origin (m_widget
->window
, &root_x
, &root_y
);
655 gdk_window_get_geometry (m_widget
->window
, &client_x
, &client_y
,
656 &width
, &height
, NULL
);
658 gdk_window_move_resize (m_widget
->window
, -client_x
, -client_y
,
659 screen_width
+ 1, screen_height
+ 1);
661 wxSetFullScreenStateX11((WXDisplay
*)GDK_DISPLAY(),
662 (WXWindow
)GDK_ROOT_WINDOW(),
663 (WXWindow
)GDK_WINDOW_XWINDOW(window
),
664 show
, &m_fsSaveFrame
, method
);
668 if (method
!= wxX11_FS_WMSPEC
)
670 // don't do it always, Metacity hates it
671 m_gdkFunc
= m_fsSaveGdkFunc
;
672 m_gdkDecor
= m_fsSaveGdkDecor
;
673 gdk_window_set_decorations(window
, (GdkWMDecoration
)m_gdkDecor
);
674 gdk_window_set_functions(window
, (GdkWMFunction
)m_gdkFunc
);
677 wxSetFullScreenStateX11((WXDisplay
*)GDK_DISPLAY(),
678 (WXWindow
)GDK_ROOT_WINDOW(),
679 (WXWindow
)GDK_WINDOW_XWINDOW(window
),
680 show
, &m_fsSaveFrame
, method
);
682 SetSize(m_fsSaveFrame
.x
, m_fsSaveFrame
.y
,
683 m_fsSaveFrame
.width
, m_fsSaveFrame
.height
);
690 // ----------------------------------------------------------------------------
691 // overridden wxWindow methods
692 // ----------------------------------------------------------------------------
694 bool wxTopLevelWindowGTK::Show( bool show
)
696 wxASSERT_MSG( (m_widget
!= NULL
), wxT("invalid frame") );
698 if (show
&& !m_sizeSet
)
700 /* by calling GtkOnSize here, we don't have to call
701 either after showing the frame, which would entail
702 much ugly flicker or from within the size_allocate
703 handler, because GTK 1.1.X forbids that. */
705 GtkOnSize( m_x
, m_y
, m_width
, m_height
);
708 return wxWindow::Show( show
);
711 void wxTopLevelWindowGTK::DoMoveWindow(int WXUNUSED(x
), int WXUNUSED(y
), int WXUNUSED(width
), int WXUNUSED(height
) )
713 wxFAIL_MSG( wxT("DoMoveWindow called for wxTopLevelWindowGTK") );
716 void wxTopLevelWindowGTK::DoSetSize( int x
, int y
, int width
, int height
, int sizeFlags
)
718 wxASSERT_MSG( (m_widget
!= NULL
), wxT("invalid frame") );
720 // this shouldn't happen: wxFrame, wxMDIParentFrame and wxMDIChildFrame have m_wxwindow
721 wxASSERT_MSG( (m_wxwindow
!= NULL
), wxT("invalid frame") );
731 int old_width
= m_width
;
732 int old_height
= m_height
;
734 if ((sizeFlags
& wxSIZE_ALLOW_MINUS_ONE
) == 0)
736 if (x
!= -1) m_x
= x
;
737 if (y
!= -1) m_y
= y
;
744 if (width
!= -1) m_width
= width
;
745 if (height
!= -1) m_height
= height
;
748 if ((sizeFlags & wxSIZE_AUTO_WIDTH) == wxSIZE_AUTO_WIDTH)
750 if (width == -1) m_width = 80;
753 if ((sizeFlags & wxSIZE_AUTO_HEIGHT) == wxSIZE_AUTO_HEIGHT)
755 if (height == -1) m_height = 26;
759 int minWidth
= GetMinWidth(),
760 minHeight
= GetMinHeight(),
761 maxWidth
= GetMaxWidth(),
762 maxHeight
= GetMaxHeight();
765 // GPE's window manager doesn't like size hints
766 // at all, esp. when the user has to use the
774 if ((minWidth
!= -1) && (m_width
< minWidth
)) m_width
= minWidth
;
775 if ((minHeight
!= -1) && (m_height
< minHeight
)) m_height
= minHeight
;
776 if ((maxWidth
!= -1) && (m_width
> maxWidth
)) m_width
= maxWidth
;
777 if ((maxHeight
!= -1) && (m_height
> maxHeight
)) m_height
= maxHeight
;
779 if ((m_x
!= -1) || (m_y
!= -1))
781 if ((m_x
!= old_x
) || (m_y
!= old_y
))
783 gtk_widget_set_uposition( m_widget
, m_x
, m_y
);
787 if ((m_width
!= old_width
) || (m_height
!= old_height
))
789 if (m_widget
->window
)
790 gdk_window_resize( m_widget
->window
, m_width
, m_height
);
792 gtk_window_set_default_size( GTK_WINDOW(m_widget
), m_width
, m_height
);
794 /* we set the size in GtkOnSize, i.e. mostly the actual resizing is
795 done either directly before the frame is shown or in idle time
796 so that different calls to SetSize() don't lead to flicker. */
803 void wxTopLevelWindowGTK::DoGetClientSize( int *width
, int *height
) const
805 wxASSERT_MSG( (m_widget
!= NULL
), wxT("invalid frame") );
807 wxWindow::DoGetClientSize( width
, height
);
811 *height
-= m_miniEdge
*2 + m_miniTitle
;
815 *width
-= m_miniEdge
*2;
819 void wxTopLevelWindowGTK::DoSetClientSize( int width
, int height
)
821 wxASSERT_MSG( (m_widget
!= NULL
), wxT("invalid frame") );
824 width
+ m_miniEdge
*2, height
+ m_miniEdge
*2 + m_miniTitle
, 0);
827 void wxTopLevelWindowGTK::GtkOnSize( int WXUNUSED(x
), int WXUNUSED(y
),
828 int width
, int height
)
830 // due to a bug in gtk, x,y are always 0
835 if (m_resizing
) return;
838 if ( m_wxwindow
== NULL
) return;
843 /* wxMDIChildFrame derives from wxFrame but it _is_ a wxWindow as it uses
844 wxWindow::Create to create it's GTK equivalent. m_mainWidget is only
845 set in wxFrame::Create so it is used to check what kind of frame we
846 have here. if m_mainWidget is NULL it is a wxMDIChildFrame and so we
847 skip the part which handles m_frameMenuBar, m_frameToolBar and (most
848 importantly) m_mainWidget */
850 int minWidth
= GetMinWidth(),
851 minHeight
= GetMinHeight(),
852 maxWidth
= GetMaxWidth(),
853 maxHeight
= GetMaxHeight();
856 // GPE's window manager doesn't like size hints
857 // at all, esp. when the user has to use the
865 if ((minWidth
!= -1) && (m_width
< minWidth
)) m_width
= minWidth
;
866 if ((minHeight
!= -1) && (m_height
< minHeight
)) m_height
= minHeight
;
867 if ((maxWidth
!= -1) && (m_width
> maxWidth
)) m_width
= maxWidth
;
868 if ((maxHeight
!= -1) && (m_height
> maxHeight
)) m_height
= maxHeight
;
873 gint flag
= 0; // GDK_HINT_POS;
876 if ((minWidth
!= -1) || (minHeight
!= -1)) flag
|= GDK_HINT_MIN_SIZE
;
877 if ((maxWidth
!= -1) || (maxHeight
!= -1)) flag
|= GDK_HINT_MAX_SIZE
;
879 geom
.min_width
= minWidth
;
880 geom
.min_height
= minHeight
;
882 // Because of the way we set GDK_HINT_MAX_SIZE above, if either of
883 // maxHeight or maxWidth is set, we must set them both, else the
884 // remaining -1 will be taken literally.
886 // I'm certain this also happens elsewhere, and is the probable
887 // cause of other such things as:
888 // Gtk-WARNING **: gtk_widget_size_allocate():
889 // attempt to allocate widget with width 65535 and height 600
890 // but I don't have time to track them all now..
892 // Really we need to encapulate all this height/width business and
893 // stop any old method from ripping at the members directly and
894 // scattering -1's without regard for who might resolve them later.
896 geom
.max_width
= ( maxHeight
== -1 ) ? maxWidth
897 : ( maxWidth
== -1 ) ? wxGetDisplaySize().GetWidth()
900 geom
.max_height
= ( maxWidth
== -1 ) ? maxHeight
// ( == -1 here )
901 : ( maxHeight
== -1 ) ? wxGetDisplaySize().GetHeight()
904 gtk_window_set_geometry_hints( GTK_WINDOW(m_widget
),
907 (GdkWindowHints
) flag
);
909 /* I revert back to wxGTK's original behaviour. m_mainWidget holds the
910 * menubar, the toolbar and the client area, which is represented by
912 * this hurts in the eye, but I don't want to call SetSize()
913 * because I don't want to call any non-native functions here. */
915 int client_x
= m_miniEdge
;
916 int client_y
= m_miniEdge
+ m_miniTitle
;
917 int client_w
= m_width
- 2*m_miniEdge
;
918 int client_h
= m_height
- 2*m_miniEdge
- m_miniTitle
;
920 gtk_pizza_set_size( GTK_PIZZA(m_mainWidget
),
922 client_x
, client_y
, client_w
, client_h
);
926 // If there is no m_mainWidget between m_widget and m_wxwindow there
927 // is no need to set the size or position of m_wxwindow.
932 // send size event to frame
933 wxSizeEvent
event( wxSize(m_width
,m_height
), GetId() );
934 event
.SetEventObject( this );
935 GetEventHandler()->ProcessEvent( event
);
940 void wxTopLevelWindowGTK::OnInternalIdle()
942 if (!m_sizeSet
&& GTK_WIDGET_REALIZED(m_wxwindow
))
944 GtkOnSize( m_x
, m_y
, m_width
, m_height
);
946 // we'll come back later
948 wxapp_install_idle_handler();
952 // set the focus if not done yet and if we can already do it
953 if ( GTK_WIDGET_REALIZED(m_wxwindow
) )
955 if ( g_delayedFocus
&&
956 wxGetTopLevelParent((wxWindow
*)g_delayedFocus
) == this )
958 wxLogTrace(_T("focus"),
959 _T("Setting focus from wxTLW::OnIdle() to %s(%s)"),
960 g_delayedFocus
->GetClassInfo()->GetClassName(),
961 g_delayedFocus
->GetLabel().c_str());
963 g_delayedFocus
->SetFocus();
964 g_delayedFocus
= NULL
;
968 wxWindow::OnInternalIdle();
970 // Synthetize activate events.
971 if ( g_sendActivateEvent
!= -1 )
973 bool activate
= g_sendActivateEvent
!= 0;
975 // if (!activate) wxPrintf( wxT("de") );
976 // wxPrintf( wxT("activate\n") );
979 g_sendActivateEvent
= -1;
981 wxTheApp
->SetActive(activate
, (wxWindow
*)g_lastActiveFrame
);
985 // ----------------------------------------------------------------------------
987 // ----------------------------------------------------------------------------
989 void wxTopLevelWindowGTK::SetTitle( const wxString
&title
)
991 wxASSERT_MSG( (m_widget
!= NULL
), wxT("invalid frame") );
994 gtk_window_set_title( GTK_WINDOW(m_widget
), wxGTK_CONV( title
) );
997 void wxTopLevelWindowGTK::SetIcon( const wxIcon
&icon
)
999 SetIcons( wxIconBundle( icon
) );
1002 void wxTopLevelWindowGTK::SetIcons( const wxIconBundle
&icons
)
1004 wxASSERT_MSG( (m_widget
!= NULL
), wxT("invalid frame") );
1006 wxTopLevelWindowBase::SetIcons( icons
);
1010 size_t max
= icons
.m_icons
.GetCount();
1012 for (size_t i
= 0; i
< max
; i
++)
1014 if (icons
.m_icons
[i
].Ok())
1016 list
= g_list_prepend(list
, icons
.m_icons
[i
].GetPixbuf());
1019 gtk_window_set_icon_list(GTK_WINDOW(m_widget
), list
);
1022 #else // !__WXGTK20__
1023 GdkWindow
* window
= m_widget
->window
;
1027 wxIcon icon
= icons
.GetIcon(-1);
1030 wxMask
*mask
= icon
.GetMask();
1031 GdkBitmap
*bm
= (GdkBitmap
*) NULL
;
1032 if (mask
) bm
= mask
->GetBitmap();
1034 gdk_window_set_icon( m_widget
->window
, (GdkWindow
*) NULL
, icon
.GetPixmap(), bm
);
1037 wxSetIconsX11( (WXDisplay
*)GDK_WINDOW_XDISPLAY( window
),
1038 (WXWindow
)GDK_WINDOW_XWINDOW( window
), icons
);
1039 #endif // !__WXGTK20__
1042 // ----------------------------------------------------------------------------
1043 // frame state: maximized/iconized/normal
1044 // ----------------------------------------------------------------------------
1046 void wxTopLevelWindowGTK::Maximize(bool maximize
)
1050 gtk_window_maximize( GTK_WINDOW( m_widget
) );
1052 gtk_window_unmaximize( GTK_WINDOW( m_widget
) );
1054 wxFAIL_MSG( _T("not implemented") );
1058 bool wxTopLevelWindowGTK::IsMaximized() const
1061 if(!m_widget
->window
)
1064 return gdk_window_get_state(m_widget
->window
) & GDK_WINDOW_STATE_MAXIMIZED
;
1066 // wxFAIL_MSG( _T("not implemented") );
1068 // This is an approximation
1073 void wxTopLevelWindowGTK::Restore()
1076 // "Present" seems similar enough to "restore"
1077 gtk_window_present( GTK_WINDOW( m_widget
) );
1079 wxFAIL_MSG( _T("not implemented") );
1083 void wxTopLevelWindowGTK::Iconize( bool iconize
)
1087 gtk_window_iconify( GTK_WINDOW( m_widget
) );
1089 gtk_window_deiconify( GTK_WINDOW( m_widget
) );
1093 GdkWindow
*window
= m_widget
->window
;
1095 // you should do it later, for example from OnCreate() handler
1096 wxCHECK_RET( window
, _T("frame not created yet - can't iconize") );
1098 XIconifyWindow( GDK_WINDOW_XDISPLAY( window
),
1099 GDK_WINDOW_XWINDOW( window
),
1100 DefaultScreen( GDK_DISPLAY() ) );
1105 bool wxTopLevelWindowGTK::IsIconized() const
1107 return m_isIconized
;
1110 void wxTopLevelWindowGTK::SetIconizeState(bool iconize
)
1112 if ( iconize
!= m_isIconized
)
1114 m_isIconized
= iconize
;
1115 (void)SendIconizeEvent(iconize
);
1119 void wxTopLevelWindowGTK::AddGrab()
1124 gtk_grab_add( m_widget
);
1126 gtk_grab_remove( m_widget
);
1130 void wxTopLevelWindowGTK::RemoveGrab()
1141 static bool do_shape_combine_region(GdkWindow
* window
, const wxRegion
& region
)
1145 if (region
.IsEmpty())
1147 gdk_window_shape_combine_mask(window
, NULL
, 0, 0);
1152 gdk_window_shape_combine_region(window
, region
.GetRegion(), 0, 0);
1154 wxBitmap bmp
= region
.ConvertToBitmap();
1155 bmp
.SetMask(new wxMask(bmp
, *wxBLACK
));
1156 GdkBitmap
* mask
= bmp
.GetMask()->GetBitmap();
1157 gdk_window_shape_combine_mask(window
, mask
, 0, 0);
1166 bool wxTopLevelWindowGTK::SetShape(const wxRegion
& region
)
1168 wxCHECK_MSG( HasFlag(wxFRAME_SHAPED
), FALSE
,
1169 _T("Shaped windows must be created with the wxFRAME_SHAPED style."));
1171 GdkWindow
*window
= NULL
;
1174 window
= GTK_PIZZA(m_wxwindow
)->bin_window
;
1175 do_shape_combine_region(window
, region
);
1177 window
= m_widget
->window
;
1178 return do_shape_combine_region(window
, region
);
1181 bool wxTopLevelWindowGTK::IsActive()
1183 return (this == (wxTopLevelWindowGTK
*)g_activeFrame
);