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 wxWindow
*topParent
= wxGetTopLevelParent(m_parent
);
455 if (topParent
&& (((GTK_IS_WINDOW(topParent
->m_widget
)) &&
456 (GetExtraStyle() & wxTOPLEVEL_EX_DIALOG
)) ||
457 (style
& wxFRAME_FLOAT_ON_PARENT
)))
459 gtk_window_set_transient_for( GTK_WINDOW(m_widget
),
460 GTK_WINDOW(topParent
->m_widget
) );
463 #if GTK_CHECK_VERSION(2,2,0)
464 if (style
& wxFRAME_NO_TASKBAR
)
466 gtk_window_set_skip_taskbar_hint(GTK_WINDOW(m_widget
), TRUE
);
471 gtk_window_set_wmclass( GTK_WINDOW(m_widget
), wxGTK_CONV( name
), wxGTK_CONV( name
) );
473 gtk_window_set_title( GTK_WINDOW(m_widget
), wxGTK_CONV( title
) );
474 GTK_WIDGET_UNSET_FLAGS( m_widget
, GTK_CAN_FOCUS
);
476 gtk_signal_connect( GTK_OBJECT(m_widget
), "delete_event",
477 GTK_SIGNAL_FUNC(gtk_frame_delete_callback
), (gpointer
)this );
479 // m_mainWidget holds the toolbar, the menubar and the client area
480 m_mainWidget
= gtk_pizza_new();
481 gtk_widget_show( m_mainWidget
);
482 GTK_WIDGET_UNSET_FLAGS( m_mainWidget
, GTK_CAN_FOCUS
);
483 gtk_container_add( GTK_CONTAINER(m_widget
), m_mainWidget
);
485 if (m_miniEdge
== 0) // wxMiniFrame has its own version.
487 // For m_mainWidget themes
488 gtk_signal_connect( GTK_OBJECT(m_mainWidget
), "expose_event",
489 GTK_SIGNAL_FUNC(gtk_window_expose_callback
), (gpointer
)this );
491 gtk_signal_connect( GTK_OBJECT(m_mainWidget
), "draw",
492 GTK_SIGNAL_FUNC(gtk_window_draw_callback
), (gpointer
)this );
496 // m_wxwindow only represents the client area without toolbar and menubar
497 m_wxwindow
= gtk_pizza_new();
498 gtk_widget_show( m_wxwindow
);
499 gtk_container_add( GTK_CONTAINER(m_mainWidget
), m_wxwindow
);
501 // we donm't allow the frame to get the focus as otherwise
502 // the frame will grab it at arbitrary focus changes
503 GTK_WIDGET_UNSET_FLAGS( m_wxwindow
, GTK_CAN_FOCUS
);
505 if (m_parent
) m_parent
->AddChild( this );
507 // the user resized the frame by dragging etc.
508 gtk_signal_connect( GTK_OBJECT(m_widget
), "size_allocate",
509 GTK_SIGNAL_FUNC(gtk_frame_size_callback
), (gpointer
)this );
513 if ((m_x
!= -1) || (m_y
!= -1))
514 gtk_widget_set_uposition( m_widget
, m_x
, m_y
);
516 gtk_window_set_default_size( GTK_WINDOW(m_widget
), m_width
, m_height
);
518 // we cannot set MWM hints and icons before the widget has
519 // been realized, so we do this directly after realization
520 gtk_signal_connect( GTK_OBJECT(m_widget
), "realize",
521 GTK_SIGNAL_FUNC(gtk_frame_realized_callback
), (gpointer
) this );
523 // the only way to get the window size is to connect to this event
524 gtk_signal_connect( GTK_OBJECT(m_widget
), "configure_event",
525 GTK_SIGNAL_FUNC(gtk_frame_configure_callback
), (gpointer
)this );
527 // map and unmap for iconized state
528 gtk_signal_connect( GTK_OBJECT(m_widget
), "map_event",
529 GTK_SIGNAL_FUNC(gtk_frame_map_callback
), (gpointer
)this );
530 gtk_signal_connect( GTK_OBJECT(m_widget
), "unmap_event",
531 GTK_SIGNAL_FUNC(gtk_frame_unmap_callback
), (gpointer
)this );
533 // the only way to get the window size is to connect to this event
534 gtk_signal_connect( GTK_OBJECT(m_widget
), "configure_event",
535 GTK_SIGNAL_FUNC(gtk_frame_configure_callback
), (gpointer
)this );
537 // disable native tab traversal
538 gtk_signal_connect( GTK_OBJECT(m_widget
), "focus",
539 GTK_SIGNAL_FUNC(gtk_frame_focus_callback
), (gpointer
)this );
542 gtk_signal_connect( GTK_OBJECT(m_widget
), "focus_in_event",
543 GTK_SIGNAL_FUNC(gtk_frame_focus_in_callback
), (gpointer
)this );
544 gtk_signal_connect( GTK_OBJECT(m_widget
), "focus_out_event",
545 GTK_SIGNAL_FUNC(gtk_frame_focus_out_callback
), (gpointer
)this );
548 if ((m_miniEdge
> 0) || (style
& wxSIMPLE_BORDER
) || (style
& wxNO_BORDER
))
555 m_gdkDecor
= (long) GDK_DECOR_BORDER
;
556 m_gdkFunc
= (long) GDK_FUNC_MOVE
;
558 // All this is for Motif Window Manager "hints" and is supposed to be
559 // recognized by other WMs as well.
560 if ((style
& wxCAPTION
) != 0)
562 m_gdkDecor
|= GDK_DECOR_TITLE
;
564 if ((style
& wxCLOSE_BOX
) != 0)
566 m_gdkFunc
|= GDK_FUNC_CLOSE
;
568 if ((style
& wxSYSTEM_MENU
) != 0)
570 m_gdkDecor
|= GDK_DECOR_MENU
;
572 if ((style
& wxMINIMIZE_BOX
) != 0)
574 m_gdkFunc
|= GDK_FUNC_MINIMIZE
;
575 m_gdkDecor
|= GDK_DECOR_MINIMIZE
;
577 if ((style
& wxMAXIMIZE_BOX
) != 0)
579 m_gdkFunc
|= GDK_FUNC_MAXIMIZE
;
580 m_gdkDecor
|= GDK_DECOR_MAXIMIZE
;
582 if ((style
& wxRESIZE_BORDER
) != 0)
584 m_gdkFunc
|= GDK_FUNC_RESIZE
;
585 m_gdkDecor
|= GDK_DECOR_RESIZEH
;
592 wxTopLevelWindowGTK::~wxTopLevelWindowGTK()
596 wxASSERT_MSG( FALSE
, _T("Window still grabbed"));
600 m_isBeingDeleted
= TRUE
;
602 // it may also be GtkScrolledWindow in the case of an MDI child
603 if (GTK_IS_WINDOW(m_widget
))
605 gtk_window_set_focus( GTK_WINDOW(m_widget
), NULL
);
608 if (g_activeFrame
== this)
609 g_activeFrame
= NULL
;
610 if (g_lastActiveFrame
== this)
611 g_lastActiveFrame
= NULL
;
616 bool wxTopLevelWindowGTK::ShowFullScreen(bool show
, long style
)
618 if (show
== m_fsIsShowing
) return FALSE
; // return what?
620 m_fsIsShowing
= show
;
622 GdkWindow
*window
= m_widget
->window
;
623 wxX11FullScreenMethod method
=
624 wxGetFullScreenMethodX11((WXDisplay
*)GDK_DISPLAY(),
625 (WXWindow
)GDK_ROOT_WINDOW());
629 m_fsSaveFlag
= style
;
630 GetPosition( &m_fsSaveFrame
.x
, &m_fsSaveFrame
.y
);
631 GetSize( &m_fsSaveFrame
.width
, &m_fsSaveFrame
.height
);
633 int screen_width
,screen_height
;
634 wxDisplaySize( &screen_width
, &screen_height
);
636 gint client_x
, client_y
, root_x
, root_y
;
639 if (method
!= wxX11_FS_WMSPEC
)
641 // don't do it always, Metacity hates it
642 m_fsSaveGdkFunc
= m_gdkFunc
;
643 m_fsSaveGdkDecor
= m_gdkDecor
;
644 m_gdkFunc
= m_gdkDecor
= 0;
645 gdk_window_set_decorations(window
, (GdkWMDecoration
)0);
646 gdk_window_set_functions(window
, (GdkWMFunction
)0);
649 gdk_window_get_origin (m_widget
->window
, &root_x
, &root_y
);
650 gdk_window_get_geometry (m_widget
->window
, &client_x
, &client_y
,
651 &width
, &height
, NULL
);
653 gdk_window_move_resize (m_widget
->window
, -client_x
, -client_y
,
654 screen_width
+ 1, screen_height
+ 1);
656 wxSetFullScreenStateX11((WXDisplay
*)GDK_DISPLAY(),
657 (WXWindow
)GDK_ROOT_WINDOW(),
658 (WXWindow
)GDK_WINDOW_XWINDOW(window
),
659 show
, &m_fsSaveFrame
, method
);
663 if (method
!= wxX11_FS_WMSPEC
)
665 // don't do it always, Metacity hates it
666 m_gdkFunc
= m_fsSaveGdkFunc
;
667 m_gdkDecor
= m_fsSaveGdkDecor
;
668 gdk_window_set_decorations(window
, (GdkWMDecoration
)m_gdkDecor
);
669 gdk_window_set_functions(window
, (GdkWMFunction
)m_gdkFunc
);
672 wxSetFullScreenStateX11((WXDisplay
*)GDK_DISPLAY(),
673 (WXWindow
)GDK_ROOT_WINDOW(),
674 (WXWindow
)GDK_WINDOW_XWINDOW(window
),
675 show
, &m_fsSaveFrame
, method
);
677 SetSize(m_fsSaveFrame
.x
, m_fsSaveFrame
.y
,
678 m_fsSaveFrame
.width
, m_fsSaveFrame
.height
);
685 // ----------------------------------------------------------------------------
686 // overridden wxWindow methods
687 // ----------------------------------------------------------------------------
689 bool wxTopLevelWindowGTK::Show( bool show
)
691 wxASSERT_MSG( (m_widget
!= NULL
), wxT("invalid frame") );
693 if (show
&& !m_sizeSet
)
695 /* by calling GtkOnSize here, we don't have to call
696 either after showing the frame, which would entail
697 much ugly flicker or from within the size_allocate
698 handler, because GTK 1.1.X forbids that. */
700 GtkOnSize( m_x
, m_y
, m_width
, m_height
);
703 return wxWindow::Show( show
);
706 void wxTopLevelWindowGTK::DoMoveWindow(int WXUNUSED(x
), int WXUNUSED(y
), int WXUNUSED(width
), int WXUNUSED(height
) )
708 wxFAIL_MSG( wxT("DoMoveWindow called for wxTopLevelWindowGTK") );
711 void wxTopLevelWindowGTK::DoSetSize( int x
, int y
, int width
, int height
, int sizeFlags
)
713 wxASSERT_MSG( (m_widget
!= NULL
), wxT("invalid frame") );
715 // this shouldn't happen: wxFrame, wxMDIParentFrame and wxMDIChildFrame have m_wxwindow
716 wxASSERT_MSG( (m_wxwindow
!= NULL
), wxT("invalid frame") );
726 int old_width
= m_width
;
727 int old_height
= m_height
;
729 if ((sizeFlags
& wxSIZE_ALLOW_MINUS_ONE
) == 0)
731 if (x
!= -1) m_x
= x
;
732 if (y
!= -1) m_y
= y
;
739 if (width
!= -1) m_width
= width
;
740 if (height
!= -1) m_height
= height
;
743 if ((sizeFlags & wxSIZE_AUTO_WIDTH) == wxSIZE_AUTO_WIDTH)
745 if (width == -1) m_width = 80;
748 if ((sizeFlags & wxSIZE_AUTO_HEIGHT) == wxSIZE_AUTO_HEIGHT)
750 if (height == -1) m_height = 26;
754 int minWidth
= GetMinWidth(),
755 minHeight
= GetMinHeight(),
756 maxWidth
= GetMaxWidth(),
757 maxHeight
= GetMaxHeight();
760 // GPE's window manager doesn't like size hints
761 // at all, esp. when the user has to use the
769 if ((minWidth
!= -1) && (m_width
< minWidth
)) m_width
= minWidth
;
770 if ((minHeight
!= -1) && (m_height
< minHeight
)) m_height
= minHeight
;
771 if ((maxWidth
!= -1) && (m_width
> maxWidth
)) m_width
= maxWidth
;
772 if ((maxHeight
!= -1) && (m_height
> maxHeight
)) m_height
= maxHeight
;
774 if ((m_x
!= -1) || (m_y
!= -1))
776 if ((m_x
!= old_x
) || (m_y
!= old_y
))
778 gtk_widget_set_uposition( m_widget
, m_x
, m_y
);
782 if ((m_width
!= old_width
) || (m_height
!= old_height
))
784 if (m_widget
->window
)
785 gdk_window_resize( m_widget
->window
, m_width
, m_height
);
787 gtk_window_set_default_size( GTK_WINDOW(m_widget
), m_width
, m_height
);
789 /* we set the size in GtkOnSize, i.e. mostly the actual resizing is
790 done either directly before the frame is shown or in idle time
791 so that different calls to SetSize() don't lead to flicker. */
798 void wxTopLevelWindowGTK::DoGetClientSize( int *width
, int *height
) const
800 wxASSERT_MSG( (m_widget
!= NULL
), wxT("invalid frame") );
802 wxWindow::DoGetClientSize( width
, height
);
806 *height
-= m_miniEdge
*2 + m_miniTitle
;
810 *width
-= m_miniEdge
*2;
814 void wxTopLevelWindowGTK::DoSetClientSize( int width
, int height
)
816 wxASSERT_MSG( (m_widget
!= NULL
), wxT("invalid frame") );
819 width
+ m_miniEdge
*2, height
+ m_miniEdge
*2 + m_miniTitle
, 0);
822 void wxTopLevelWindowGTK::GtkOnSize( int WXUNUSED(x
), int WXUNUSED(y
),
823 int width
, int height
)
825 // due to a bug in gtk, x,y are always 0
830 if (m_resizing
) return;
833 if ( m_wxwindow
== NULL
) return;
838 /* wxMDIChildFrame derives from wxFrame but it _is_ a wxWindow as it uses
839 wxWindow::Create to create it's GTK equivalent. m_mainWidget is only
840 set in wxFrame::Create so it is used to check what kind of frame we
841 have here. if m_mainWidget is NULL it is a wxMDIChildFrame and so we
842 skip the part which handles m_frameMenuBar, m_frameToolBar and (most
843 importantly) m_mainWidget */
845 int minWidth
= GetMinWidth(),
846 minHeight
= GetMinHeight(),
847 maxWidth
= GetMaxWidth(),
848 maxHeight
= GetMaxHeight();
851 // GPE's window manager doesn't like size hints
852 // at all, esp. when the user has to use the
860 if ((minWidth
!= -1) && (m_width
< minWidth
)) m_width
= minWidth
;
861 if ((minHeight
!= -1) && (m_height
< minHeight
)) m_height
= minHeight
;
862 if ((maxWidth
!= -1) && (m_width
> maxWidth
)) m_width
= maxWidth
;
863 if ((maxHeight
!= -1) && (m_height
> maxHeight
)) m_height
= maxHeight
;
868 gint flag
= 0; // GDK_HINT_POS;
871 if ((minWidth
!= -1) || (minHeight
!= -1)) flag
|= GDK_HINT_MIN_SIZE
;
872 if ((maxWidth
!= -1) || (maxHeight
!= -1)) flag
|= GDK_HINT_MAX_SIZE
;
874 geom
.min_width
= minWidth
;
875 geom
.min_height
= minHeight
;
877 // Because of the way we set GDK_HINT_MAX_SIZE above, if either of
878 // maxHeight or maxWidth is set, we must set them both, else the
879 // remaining -1 will be taken literally.
881 // I'm certain this also happens elsewhere, and is the probable
882 // cause of other such things as:
883 // Gtk-WARNING **: gtk_widget_size_allocate():
884 // attempt to allocate widget with width 65535 and height 600
885 // but I don't have time to track them all now..
887 // Really we need to encapulate all this height/width business and
888 // stop any old method from ripping at the members directly and
889 // scattering -1's without regard for who might resolve them later.
891 geom
.max_width
= ( maxHeight
== -1 ) ? maxWidth
892 : ( maxWidth
== -1 ) ? wxGetDisplaySize().GetWidth()
895 geom
.max_height
= ( maxWidth
== -1 ) ? maxHeight
// ( == -1 here )
896 : ( maxHeight
== -1 ) ? wxGetDisplaySize().GetHeight()
899 gtk_window_set_geometry_hints( GTK_WINDOW(m_widget
),
902 (GdkWindowHints
) flag
);
904 /* I revert back to wxGTK's original behaviour. m_mainWidget holds the
905 * menubar, the toolbar and the client area, which is represented by
907 * this hurts in the eye, but I don't want to call SetSize()
908 * because I don't want to call any non-native functions here. */
910 int client_x
= m_miniEdge
;
911 int client_y
= m_miniEdge
+ m_miniTitle
;
912 int client_w
= m_width
- 2*m_miniEdge
;
913 int client_h
= m_height
- 2*m_miniEdge
- m_miniTitle
;
915 gtk_pizza_set_size( GTK_PIZZA(m_mainWidget
),
917 client_x
, client_y
, client_w
, client_h
);
921 // If there is no m_mainWidget between m_widget and m_wxwindow there
922 // is no need to set the size or position of m_wxwindow.
927 // send size event to frame
928 wxSizeEvent
event( wxSize(m_width
,m_height
), GetId() );
929 event
.SetEventObject( this );
930 GetEventHandler()->ProcessEvent( event
);
935 void wxTopLevelWindowGTK::OnInternalIdle()
937 if (!m_sizeSet
&& GTK_WIDGET_REALIZED(m_wxwindow
))
939 GtkOnSize( m_x
, m_y
, m_width
, m_height
);
941 // we'll come back later
943 wxapp_install_idle_handler();
947 // set the focus if not done yet and if we can already do it
948 if ( GTK_WIDGET_REALIZED(m_wxwindow
) )
950 if ( g_delayedFocus
&&
951 wxGetTopLevelParent((wxWindow
*)g_delayedFocus
) == this )
953 wxLogTrace(_T("focus"),
954 _T("Setting focus from wxTLW::OnIdle() to %s(%s)"),
955 g_delayedFocus
->GetClassInfo()->GetClassName(),
956 g_delayedFocus
->GetLabel().c_str());
958 g_delayedFocus
->SetFocus();
959 g_delayedFocus
= NULL
;
963 wxWindow::OnInternalIdle();
965 // Synthetize activate events.
966 if ( g_sendActivateEvent
!= -1 )
968 bool activate
= g_sendActivateEvent
!= 0;
971 g_sendActivateEvent
= -1;
973 wxTheApp
->SetActive(activate
, (wxWindow
*)g_lastActiveFrame
);
977 // ----------------------------------------------------------------------------
979 // ----------------------------------------------------------------------------
981 void wxTopLevelWindowGTK::SetTitle( const wxString
&title
)
983 wxASSERT_MSG( (m_widget
!= NULL
), wxT("invalid frame") );
986 gtk_window_set_title( GTK_WINDOW(m_widget
), wxGTK_CONV( title
) );
989 void wxTopLevelWindowGTK::SetIcon( const wxIcon
&icon
)
991 SetIcons( wxIconBundle( icon
) );
994 void wxTopLevelWindowGTK::SetIcons( const wxIconBundle
&icons
)
996 wxASSERT_MSG( (m_widget
!= NULL
), wxT("invalid frame") );
998 wxTopLevelWindowBase::SetIcons( icons
);
1002 size_t max
= icons
.m_icons
.GetCount();
1004 for (size_t i
= 0; i
< max
; i
++)
1006 if (icons
.m_icons
[i
].Ok())
1008 list
= g_list_prepend(list
, icons
.m_icons
[i
].GetPixbuf());
1011 gtk_window_set_icon_list(GTK_WINDOW(m_widget
), list
);
1014 #else // !__WXGTK20__
1015 GdkWindow
* window
= m_widget
->window
;
1019 wxIcon icon
= icons
.GetIcon(-1);
1022 wxMask
*mask
= icon
.GetMask();
1023 GdkBitmap
*bm
= (GdkBitmap
*) NULL
;
1024 if (mask
) bm
= mask
->GetBitmap();
1026 gdk_window_set_icon( m_widget
->window
, (GdkWindow
*) NULL
, icon
.GetPixmap(), bm
);
1029 wxSetIconsX11( (WXDisplay
*)GDK_WINDOW_XDISPLAY( window
),
1030 (WXWindow
)GDK_WINDOW_XWINDOW( window
), icons
);
1031 #endif // !__WXGTK20__
1034 // ----------------------------------------------------------------------------
1035 // frame state: maximized/iconized/normal
1036 // ----------------------------------------------------------------------------
1038 void wxTopLevelWindowGTK::Maximize(bool maximize
)
1042 gtk_window_maximize( GTK_WINDOW( m_widget
) );
1044 gtk_window_unmaximize( GTK_WINDOW( m_widget
) );
1046 wxFAIL_MSG( _T("not implemented") );
1050 bool wxTopLevelWindowGTK::IsMaximized() const
1053 if(!m_widget
->window
)
1056 return gdk_window_get_state(m_widget
->window
) & GDK_WINDOW_STATE_MAXIMIZED
;
1058 // wxFAIL_MSG( _T("not implemented") );
1060 // This is an approximation
1065 void wxTopLevelWindowGTK::Restore()
1068 // "Present" seems similar enough to "restore"
1069 gtk_window_present( GTK_WINDOW( m_widget
) );
1071 wxFAIL_MSG( _T("not implemented") );
1075 void wxTopLevelWindowGTK::Iconize( bool iconize
)
1079 gtk_window_iconify( GTK_WINDOW( m_widget
) );
1081 gtk_window_deiconify( GTK_WINDOW( m_widget
) );
1085 GdkWindow
*window
= m_widget
->window
;
1087 // you should do it later, for example from OnCreate() handler
1088 wxCHECK_RET( window
, _T("frame not created yet - can't iconize") );
1090 XIconifyWindow( GDK_WINDOW_XDISPLAY( window
),
1091 GDK_WINDOW_XWINDOW( window
),
1092 DefaultScreen( GDK_DISPLAY() ) );
1097 bool wxTopLevelWindowGTK::IsIconized() const
1099 return m_isIconized
;
1102 void wxTopLevelWindowGTK::SetIconizeState(bool iconize
)
1104 if ( iconize
!= m_isIconized
)
1106 m_isIconized
= iconize
;
1107 (void)SendIconizeEvent(iconize
);
1111 void wxTopLevelWindowGTK::AddGrab()
1116 gtk_grab_add( m_widget
);
1118 gtk_grab_remove( m_widget
);
1122 void wxTopLevelWindowGTK::RemoveGrab()
1133 static bool do_shape_combine_region(GdkWindow
* window
, const wxRegion
& region
)
1137 if (region
.IsEmpty())
1139 gdk_window_shape_combine_mask(window
, NULL
, 0, 0);
1144 gdk_window_shape_combine_region(window
, region
.GetRegion(), 0, 0);
1146 wxBitmap bmp
= region
.ConvertToBitmap();
1147 bmp
.SetMask(new wxMask(bmp
, *wxBLACK
));
1148 GdkBitmap
* mask
= bmp
.GetMask()->GetBitmap();
1149 gdk_window_shape_combine_mask(window
, mask
, 0, 0);
1158 bool wxTopLevelWindowGTK::SetShape(const wxRegion
& region
)
1160 wxCHECK_MSG( HasFlag(wxFRAME_SHAPED
), FALSE
,
1161 _T("Shaped windows must be created with the wxFRAME_SHAPED style."));
1163 GdkWindow
*window
= NULL
;
1166 window
= GTK_PIZZA(m_wxwindow
)->bin_window
;
1167 do_shape_combine_region(window
, region
);
1169 window
= m_widget
->window
;
1170 return do_shape_combine_region(window
, region
);
1173 bool wxTopLevelWindowGTK::IsActive()
1175 return (this == (wxTopLevelWindowGTK
*)g_activeFrame
);