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
31 #include "wx/toplevel.h"
33 #include "wx/dialog.h"
34 #include "wx/control.h"
36 #include "wx/dcclient.h"
37 #include "wx/gtk/private.h"
39 #include "wx/settings.h"
44 #include <gdk/gdkkeysyms.h>
47 #include "wx/gtk/win_gtk.h"
49 #include "wx/unix/utilsx11.h"
52 #include <X11/Xatom.h>
54 // ----------------------------------------------------------------------------
56 // ----------------------------------------------------------------------------
58 extern void wxapp_install_idle_handler();
61 // ----------------------------------------------------------------------------
63 // ----------------------------------------------------------------------------
65 extern wxList wxPendingDelete
;
67 extern int g_openDialogs
;
68 extern wxWindowGTK
*g_delayedFocus
;
70 // the frame that is currently active (i.e. its child has focus). It is
71 // used to generate wxActivateEvents
72 static wxTopLevelWindowGTK
*g_activeFrame
= (wxTopLevelWindowGTK
*) NULL
;
73 static wxTopLevelWindowGTK
*g_lastActiveFrame
= (wxTopLevelWindowGTK
*) NULL
;
75 // if we detect that the app has got/lost the focus, we set this variable to
76 // either TRUE or FALSE and an activate event will be sent during the next
77 // OnIdle() call and it is reset to -1: this value means that we shouldn't
78 // send any activate events at all
79 static int g_sendActivateEvent
= -1;
81 //-----------------------------------------------------------------------------
83 //-----------------------------------------------------------------------------
85 static gint
gtk_frame_focus_in_callback( GtkWidget
*widget
,
86 GdkEvent
*WXUNUSED(event
),
87 wxTopLevelWindowGTK
*win
)
90 wxapp_install_idle_handler();
92 switch ( g_sendActivateEvent
)
95 // we've got focus from outside, synthetize wxActivateEvent
96 g_sendActivateEvent
= 1;
100 // another our window just lost focus, it was already ours before
101 // - don't send any wxActivateEvent
102 g_sendActivateEvent
= -1;
107 g_lastActiveFrame
= g_activeFrame
;
109 // wxPrintf( wxT("active: %s\n"), win->GetTitle().c_str() );
111 wxLogTrace(wxT("activate"), wxT("Activating frame %p (from focus_in)"), g_activeFrame
);
112 wxActivateEvent
event(wxEVT_ACTIVATE
, TRUE
, g_activeFrame
->GetId());
113 event
.SetEventObject(g_activeFrame
);
114 g_activeFrame
->GetEventHandler()->ProcessEvent(event
);
119 //-----------------------------------------------------------------------------
121 //-----------------------------------------------------------------------------
123 static gint
gtk_frame_focus_out_callback( GtkWidget
*widget
,
124 GdkEventFocus
*WXUNUSED(gdk_event
),
125 wxTopLevelWindowGTK
*win
)
128 wxapp_install_idle_handler();
130 // if the focus goes out of our app alltogether, OnIdle() will send
131 // wxActivateEvent, otherwise gtk_window_focus_in_callback() will reset
132 // g_sendActivateEvent to -1
133 g_sendActivateEvent
= 0;
135 // wxASSERT_MSG( (g_activeFrame == win), wxT("TLW deactivatd although it wasn't active") );
137 // wxPrintf( wxT("inactive: %s\n"), win->GetTitle().c_str() );
141 wxLogTrace(wxT("activate"), wxT("Activating frame %p (from focus_in)"), g_activeFrame
);
142 wxActivateEvent
event(wxEVT_ACTIVATE
, FALSE
, g_activeFrame
->GetId());
143 event
.SetEventObject(g_activeFrame
);
144 g_activeFrame
->GetEventHandler()->ProcessEvent(event
);
146 g_activeFrame
= NULL
;
152 //-----------------------------------------------------------------------------
153 // "focus" from m_window
154 //-----------------------------------------------------------------------------
156 static gint
gtk_frame_focus_callback( GtkWidget
*widget
, GtkDirectionType
WXUNUSED(d
), wxWindow
*WXUNUSED(win
) )
159 wxapp_install_idle_handler();
161 // This disables GTK's tab traversal
162 gtk_signal_emit_stop_by_name( GTK_OBJECT(widget
), "focus" );
166 //-----------------------------------------------------------------------------
168 //-----------------------------------------------------------------------------
170 static void gtk_frame_size_callback( GtkWidget
*WXUNUSED(widget
), GtkAllocation
* alloc
, wxTopLevelWindowGTK
*win
)
173 wxapp_install_idle_handler();
178 if ((win
->m_width
!= alloc
->width
) || (win
->m_height
!= alloc
->height
))
181 wxPrintf( "OnSize from " );
182 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
183 wxPrintf( win->GetClassInfo()->GetClassName() );
184 wxPrintf( " %d %d %d %d\n", (int)alloc->x,
187 (int)alloc->height );
190 win
->m_width
= alloc
->width
;
191 win
->m_height
= alloc
->height
;
192 win
->GtkUpdateSize();
196 //-----------------------------------------------------------------------------
198 //-----------------------------------------------------------------------------
200 static gint
gtk_frame_delete_callback( GtkWidget
*WXUNUSED(widget
), GdkEvent
*WXUNUSED(event
), wxTopLevelWindowGTK
*win
)
203 wxapp_install_idle_handler();
205 if (win
->IsEnabled() &&
206 (g_openDialogs
== 0 || (win
->GetExtraStyle() & wxTOPLEVEL_EX_DIALOG
) ||
214 //-----------------------------------------------------------------------------
216 //-----------------------------------------------------------------------------
219 gtk_frame_configure_callback( GtkWidget
*WXUNUSED(widget
), GdkEventConfigure
*WXUNUSED(event
), wxTopLevelWindowGTK
*win
)
222 wxapp_install_idle_handler();
224 if (!win
->m_hasVMT
|| !win
->IsShown())
229 gdk_window_get_root_origin( win
->m_widget
->window
, &x
, &y
);
233 wxMoveEvent
mevent( wxPoint(win
->m_x
,win
->m_y
), win
->GetId() );
234 mevent
.SetEventObject( win
);
235 win
->GetEventHandler()->ProcessEvent( mevent
);
240 //-----------------------------------------------------------------------------
241 // "realize" from m_widget
242 //-----------------------------------------------------------------------------
244 // we cannot MWM hints and icons before the widget has been realized,
245 // so we do this directly after realization
248 gtk_frame_realized_callback( GtkWidget
* WXUNUSED(widget
),
249 wxTopLevelWindowGTK
*win
)
252 wxapp_install_idle_handler();
254 // All this is for Motif Window Manager "hints" and is supposed to be
255 // recognized by other WM as well. Not tested.
256 gdk_window_set_decorations(win
->m_widget
->window
,
257 (GdkWMDecoration
)win
->m_gdkDecor
);
258 gdk_window_set_functions(win
->m_widget
->window
,
259 (GdkWMFunction
)win
->m_gdkFunc
);
261 // GTK's shrinking/growing policy
262 if ((win
->m_gdkFunc
& GDK_FUNC_RESIZE
) == 0)
263 gtk_window_set_policy(GTK_WINDOW(win
->m_widget
), 0, 0, 1);
265 gtk_window_set_policy(GTK_WINDOW(win
->m_widget
), 1, 1, 1);
268 wxIconBundle iconsOld
= win
->GetIcons();
269 if ( iconsOld
.GetIcon(-1).Ok() )
271 win
->SetIcon( wxNullIcon
);
272 win
->SetIcons( iconsOld
);
276 //-----------------------------------------------------------------------------
277 // "map_event" from m_widget
278 //-----------------------------------------------------------------------------
281 gtk_frame_map_callback( GtkWidget
* WXUNUSED(widget
),
282 GdkEvent
* WXUNUSED(event
),
283 wxTopLevelWindow
*win
)
285 win
->SetIconizeState(FALSE
);
288 //-----------------------------------------------------------------------------
289 // "unmap_event" from m_widget
290 //-----------------------------------------------------------------------------
293 gtk_frame_unmap_callback( GtkWidget
* WXUNUSED(widget
),
294 GdkEvent
* WXUNUSED(event
),
295 wxTopLevelWindow
*win
)
297 win
->SetIconizeState(TRUE
);
300 //-----------------------------------------------------------------------------
301 // "expose_event" of m_client
302 //-----------------------------------------------------------------------------
304 static int gtk_window_expose_callback( GtkWidget
*widget
, GdkEventExpose
*gdk_event
, wxWindow
*win
)
306 GtkPizza
*pizza
= GTK_PIZZA(widget
);
308 gtk_paint_flat_box (win
->m_widget
->style
,
309 pizza
->bin_window
, GTK_STATE_NORMAL
,
319 //-----------------------------------------------------------------------------
320 // "draw" of m_client
321 //-----------------------------------------------------------------------------
325 static void gtk_window_draw_callback( GtkWidget
*widget
, GdkRectangle
*rect
, wxWindow
*win
)
327 GtkPizza
*pizza
= GTK_PIZZA(widget
);
329 gtk_paint_flat_box (win
->m_widget
->style
,
330 pizza
->bin_window
, GTK_STATE_NORMAL
,
340 // ----------------------------------------------------------------------------
341 // wxTopLevelWindowGTK itself
342 // ----------------------------------------------------------------------------
344 //-----------------------------------------------------------------------------
345 // InsertChild for wxTopLevelWindowGTK
346 //-----------------------------------------------------------------------------
348 /* Callback for wxTopLevelWindowGTK. This very strange beast has to be used because
349 * C++ has no virtual methods in a constructor. We have to emulate a
350 * virtual function here as wxWidgets requires different ways to insert
351 * a child in container classes. */
353 static void wxInsertChildInTopLevelWindow( wxTopLevelWindowGTK
* parent
, wxWindow
* child
)
355 wxASSERT( GTK_IS_WIDGET(child
->m_widget
) );
357 if (!parent
->m_insertInClientArea
)
359 // these are outside the client area
360 wxTopLevelWindowGTK
* frame
= (wxTopLevelWindowGTK
*) parent
;
361 gtk_pizza_put( GTK_PIZZA(frame
->m_mainWidget
),
362 GTK_WIDGET(child
->m_widget
),
370 // these are inside the client area
371 gtk_pizza_put( GTK_PIZZA(parent
->m_wxwindow
),
372 GTK_WIDGET(child
->m_widget
),
379 // resize on OnInternalIdle
380 parent
->GtkUpdateSize();
383 // ----------------------------------------------------------------------------
384 // wxTopLevelWindowGTK creation
385 // ----------------------------------------------------------------------------
387 void wxTopLevelWindowGTK::Init()
392 m_mainWidget
= (GtkWidget
*) NULL
;
393 m_insertInClientArea
= TRUE
;
394 m_isIconized
= FALSE
;
395 m_fsIsShowing
= FALSE
;
396 m_themeEnabled
= TRUE
;
397 m_gdkDecor
= m_gdkFunc
= 0;
401 bool wxTopLevelWindowGTK::Create( wxWindow
*parent
,
403 const wxString
& title
,
405 const wxSize
& sizeOrig
,
407 const wxString
&name
)
409 // always create a frame of some reasonable, even if arbitrary, size (at
410 // least for MSW compatibility)
411 wxSize size
= sizeOrig
;
412 size
.x
= WidthDefault(size
.x
);
413 size
.y
= HeightDefault(size
.y
);
415 wxTopLevelWindows
.Append( this );
417 m_needParent
= FALSE
;
419 if (!PreCreation( parent
, pos
, size
) ||
420 !CreateBase( parent
, id
, pos
, size
, style
, wxDefaultValidator
, name
))
422 wxFAIL_MSG( wxT("wxTopLevelWindowGTK creation failed") );
428 m_insertCallback
= (wxInsertChildFunction
) wxInsertChildInTopLevelWindow
;
430 // NB: m_widget may be !=NULL if it was created by derived class' Create,
431 // e.g. in wxTaskBarIconAreaGTK
432 if (m_widget
== NULL
)
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(GTK_WINDOW_TOPLEVEL
);
452 if (style
& wxFRAME_TOOL_WINDOW
)
453 gtk_window_set_type_hint(GTK_WINDOW(m_widget
),
454 GDK_WINDOW_TYPE_HINT_UTILITY
);
460 wxWindow
*topParent
= wxGetTopLevelParent(m_parent
);
461 if (topParent
&& (((GTK_IS_WINDOW(topParent
->m_widget
)) &&
462 (GetExtraStyle() & wxTOPLEVEL_EX_DIALOG
)) ||
463 (style
& wxFRAME_FLOAT_ON_PARENT
)))
465 gtk_window_set_transient_for( GTK_WINDOW(m_widget
),
466 GTK_WINDOW(topParent
->m_widget
) );
469 #if GTK_CHECK_VERSION(2,2,0)
470 if (style
& wxFRAME_NO_TASKBAR
)
472 gtk_window_set_skip_taskbar_hint(GTK_WINDOW(m_widget
), TRUE
);
477 gtk_window_set_wmclass( GTK_WINDOW(m_widget
), wxGTK_CONV( name
), wxGTK_CONV( name
) );
479 gtk_window_set_title( GTK_WINDOW(m_widget
), wxGTK_CONV( title
) );
480 GTK_WIDGET_UNSET_FLAGS( m_widget
, GTK_CAN_FOCUS
);
482 gtk_signal_connect( GTK_OBJECT(m_widget
), "delete_event",
483 GTK_SIGNAL_FUNC(gtk_frame_delete_callback
), (gpointer
)this );
485 // m_mainWidget holds the toolbar, the menubar and the client area
486 m_mainWidget
= gtk_pizza_new();
487 gtk_widget_show( m_mainWidget
);
488 GTK_WIDGET_UNSET_FLAGS( m_mainWidget
, GTK_CAN_FOCUS
);
489 gtk_container_add( GTK_CONTAINER(m_widget
), m_mainWidget
);
491 if (m_miniEdge
== 0) // wxMiniFrame has its own version.
493 // For m_mainWidget themes
494 gtk_signal_connect( GTK_OBJECT(m_mainWidget
), "expose_event",
495 GTK_SIGNAL_FUNC(gtk_window_expose_callback
), (gpointer
)this );
497 gtk_signal_connect( GTK_OBJECT(m_mainWidget
), "draw",
498 GTK_SIGNAL_FUNC(gtk_window_draw_callback
), (gpointer
)this );
502 // m_wxwindow only represents the client area without toolbar and menubar
503 m_wxwindow
= gtk_pizza_new();
504 gtk_widget_show( m_wxwindow
);
505 gtk_container_add( GTK_CONTAINER(m_mainWidget
), m_wxwindow
);
507 // we donm't allow the frame to get the focus as otherwise
508 // the frame will grab it at arbitrary focus changes
509 GTK_WIDGET_UNSET_FLAGS( m_wxwindow
, GTK_CAN_FOCUS
);
511 if (m_parent
) m_parent
->AddChild( this );
513 // the user resized the frame by dragging etc.
514 gtk_signal_connect( GTK_OBJECT(m_widget
), "size_allocate",
515 GTK_SIGNAL_FUNC(gtk_frame_size_callback
), (gpointer
)this );
519 if ((m_x
!= -1) || (m_y
!= -1))
520 gtk_widget_set_uposition( m_widget
, m_x
, m_y
);
522 gtk_window_set_default_size( GTK_WINDOW(m_widget
), m_width
, m_height
);
524 // we cannot set MWM hints and icons before the widget has
525 // been realized, so we do this directly after realization
526 gtk_signal_connect( GTK_OBJECT(m_widget
), "realize",
527 GTK_SIGNAL_FUNC(gtk_frame_realized_callback
), (gpointer
) this );
529 // the only way to get the window size is to connect to this event
530 gtk_signal_connect( GTK_OBJECT(m_widget
), "configure_event",
531 GTK_SIGNAL_FUNC(gtk_frame_configure_callback
), (gpointer
)this );
533 // map and unmap for iconized state
534 gtk_signal_connect( GTK_OBJECT(m_widget
), "map_event",
535 GTK_SIGNAL_FUNC(gtk_frame_map_callback
), (gpointer
)this );
536 gtk_signal_connect( GTK_OBJECT(m_widget
), "unmap_event",
537 GTK_SIGNAL_FUNC(gtk_frame_unmap_callback
), (gpointer
)this );
539 // the only way to get the window size is to connect to this event
540 gtk_signal_connect( GTK_OBJECT(m_widget
), "configure_event",
541 GTK_SIGNAL_FUNC(gtk_frame_configure_callback
), (gpointer
)this );
543 // disable native tab traversal
544 gtk_signal_connect( GTK_OBJECT(m_widget
), "focus",
545 GTK_SIGNAL_FUNC(gtk_frame_focus_callback
), (gpointer
)this );
548 gtk_signal_connect( GTK_OBJECT(m_widget
), "focus_in_event",
549 GTK_SIGNAL_FUNC(gtk_frame_focus_in_callback
), (gpointer
)this );
550 gtk_signal_connect( GTK_OBJECT(m_widget
), "focus_out_event",
551 GTK_SIGNAL_FUNC(gtk_frame_focus_out_callback
), (gpointer
)this );
554 if ((m_miniEdge
> 0) || (style
& wxSIMPLE_BORDER
) || (style
& wxNO_BORDER
))
561 m_gdkDecor
= (long) GDK_DECOR_BORDER
;
562 m_gdkFunc
= (long) GDK_FUNC_MOVE
;
564 // All this is for Motif Window Manager "hints" and is supposed to be
565 // recognized by other WMs as well.
566 if ((style
& wxCAPTION
) != 0)
568 m_gdkDecor
|= GDK_DECOR_TITLE
;
570 if ((style
& wxCLOSE_BOX
) != 0)
572 m_gdkFunc
|= GDK_FUNC_CLOSE
;
574 if ((style
& wxSYSTEM_MENU
) != 0)
576 m_gdkDecor
|= GDK_DECOR_MENU
;
578 if ((style
& wxMINIMIZE_BOX
) != 0)
580 m_gdkFunc
|= GDK_FUNC_MINIMIZE
;
581 m_gdkDecor
|= GDK_DECOR_MINIMIZE
;
583 if ((style
& wxMAXIMIZE_BOX
) != 0)
585 m_gdkFunc
|= GDK_FUNC_MAXIMIZE
;
586 m_gdkDecor
|= GDK_DECOR_MAXIMIZE
;
588 if ((style
& wxRESIZE_BORDER
) != 0)
590 m_gdkFunc
|= GDK_FUNC_RESIZE
;
591 m_gdkDecor
|= GDK_DECOR_RESIZEH
;
598 wxTopLevelWindowGTK::~wxTopLevelWindowGTK()
602 wxASSERT_MSG( FALSE
, _T("Window still grabbed"));
606 m_isBeingDeleted
= TRUE
;
608 // it may also be GtkScrolledWindow in the case of an MDI child
609 if (GTK_IS_WINDOW(m_widget
))
611 gtk_window_set_focus( GTK_WINDOW(m_widget
), NULL
);
614 if (g_activeFrame
== this)
615 g_activeFrame
= NULL
;
616 if (g_lastActiveFrame
== this)
617 g_lastActiveFrame
= NULL
;
622 bool wxTopLevelWindowGTK::ShowFullScreen(bool show
, long style
)
624 if (show
== m_fsIsShowing
) return FALSE
; // return what?
626 m_fsIsShowing
= show
;
628 GdkWindow
*window
= m_widget
->window
;
629 wxX11FullScreenMethod method
=
630 wxGetFullScreenMethodX11((WXDisplay
*)GDK_DISPLAY(),
631 (WXWindow
)GDK_ROOT_WINDOW());
635 m_fsSaveFlag
= style
;
636 GetPosition( &m_fsSaveFrame
.x
, &m_fsSaveFrame
.y
);
637 GetSize( &m_fsSaveFrame
.width
, &m_fsSaveFrame
.height
);
639 int screen_width
,screen_height
;
640 wxDisplaySize( &screen_width
, &screen_height
);
642 gint client_x
, client_y
, root_x
, root_y
;
645 if (method
!= wxX11_FS_WMSPEC
)
647 // don't do it always, Metacity hates it
648 m_fsSaveGdkFunc
= m_gdkFunc
;
649 m_fsSaveGdkDecor
= m_gdkDecor
;
650 m_gdkFunc
= m_gdkDecor
= 0;
651 gdk_window_set_decorations(window
, (GdkWMDecoration
)0);
652 gdk_window_set_functions(window
, (GdkWMFunction
)0);
655 gdk_window_get_origin (m_widget
->window
, &root_x
, &root_y
);
656 gdk_window_get_geometry (m_widget
->window
, &client_x
, &client_y
,
657 &width
, &height
, NULL
);
659 gdk_window_move_resize (m_widget
->window
, -client_x
, -client_y
,
660 screen_width
+ 1, screen_height
+ 1);
662 wxSetFullScreenStateX11((WXDisplay
*)GDK_DISPLAY(),
663 (WXWindow
)GDK_ROOT_WINDOW(),
664 (WXWindow
)GDK_WINDOW_XWINDOW(window
),
665 show
, &m_fsSaveFrame
, method
);
669 if (method
!= wxX11_FS_WMSPEC
)
671 // don't do it always, Metacity hates it
672 m_gdkFunc
= m_fsSaveGdkFunc
;
673 m_gdkDecor
= m_fsSaveGdkDecor
;
674 gdk_window_set_decorations(window
, (GdkWMDecoration
)m_gdkDecor
);
675 gdk_window_set_functions(window
, (GdkWMFunction
)m_gdkFunc
);
678 wxSetFullScreenStateX11((WXDisplay
*)GDK_DISPLAY(),
679 (WXWindow
)GDK_ROOT_WINDOW(),
680 (WXWindow
)GDK_WINDOW_XWINDOW(window
),
681 show
, &m_fsSaveFrame
, method
);
683 SetSize(m_fsSaveFrame
.x
, m_fsSaveFrame
.y
,
684 m_fsSaveFrame
.width
, m_fsSaveFrame
.height
);
691 // ----------------------------------------------------------------------------
692 // overridden wxWindow methods
693 // ----------------------------------------------------------------------------
695 bool wxTopLevelWindowGTK::Show( bool show
)
697 wxASSERT_MSG( (m_widget
!= NULL
), wxT("invalid frame") );
699 if (show
&& !m_sizeSet
)
701 /* by calling GtkOnSize here, we don't have to call
702 either after showing the frame, which would entail
703 much ugly flicker or from within the size_allocate
704 handler, because GTK 1.1.X forbids that. */
706 GtkOnSize( m_x
, m_y
, m_width
, m_height
);
709 return wxWindow::Show( show
);
712 void wxTopLevelWindowGTK::DoMoveWindow(int WXUNUSED(x
), int WXUNUSED(y
), int WXUNUSED(width
), int WXUNUSED(height
) )
714 wxFAIL_MSG( wxT("DoMoveWindow called for wxTopLevelWindowGTK") );
717 void wxTopLevelWindowGTK::DoSetSize( int x
, int y
, int width
, int height
, int sizeFlags
)
719 wxASSERT_MSG( (m_widget
!= NULL
), wxT("invalid frame") );
721 // this shouldn't happen: wxFrame, wxMDIParentFrame and wxMDIChildFrame have m_wxwindow
722 wxASSERT_MSG( (m_wxwindow
!= NULL
), wxT("invalid frame") );
732 int old_width
= m_width
;
733 int old_height
= m_height
;
735 if ((sizeFlags
& wxSIZE_ALLOW_MINUS_ONE
) == 0)
737 if (x
!= -1) m_x
= x
;
738 if (y
!= -1) m_y
= y
;
745 if (width
!= -1) m_width
= width
;
746 if (height
!= -1) m_height
= height
;
749 if ((sizeFlags & wxSIZE_AUTO_WIDTH) == wxSIZE_AUTO_WIDTH)
751 if (width == -1) m_width = 80;
754 if ((sizeFlags & wxSIZE_AUTO_HEIGHT) == wxSIZE_AUTO_HEIGHT)
756 if (height == -1) m_height = 26;
760 int minWidth
= GetMinWidth(),
761 minHeight
= GetMinHeight(),
762 maxWidth
= GetMaxWidth(),
763 maxHeight
= GetMaxHeight();
766 // GPE's window manager doesn't like size hints
767 // at all, esp. when the user has to use the
775 if ((minWidth
!= -1) && (m_width
< minWidth
)) m_width
= minWidth
;
776 if ((minHeight
!= -1) && (m_height
< minHeight
)) m_height
= minHeight
;
777 if ((maxWidth
!= -1) && (m_width
> maxWidth
)) m_width
= maxWidth
;
778 if ((maxHeight
!= -1) && (m_height
> maxHeight
)) m_height
= maxHeight
;
780 if ((m_x
!= -1) || (m_y
!= -1))
782 if ((m_x
!= old_x
) || (m_y
!= old_y
))
784 gtk_widget_set_uposition( m_widget
, m_x
, m_y
);
788 if ((m_width
!= old_width
) || (m_height
!= old_height
))
790 if (m_widget
->window
)
791 gdk_window_resize( m_widget
->window
, m_width
, m_height
);
793 gtk_window_set_default_size( GTK_WINDOW(m_widget
), m_width
, m_height
);
795 /* we set the size in GtkOnSize, i.e. mostly the actual resizing is
796 done either directly before the frame is shown or in idle time
797 so that different calls to SetSize() don't lead to flicker. */
804 void wxTopLevelWindowGTK::DoGetClientSize( int *width
, int *height
) const
806 wxASSERT_MSG( (m_widget
!= NULL
), wxT("invalid frame") );
808 wxWindow::DoGetClientSize( width
, height
);
812 *height
-= m_miniEdge
*2 + m_miniTitle
;
816 *width
-= m_miniEdge
*2;
820 void wxTopLevelWindowGTK::DoSetClientSize( int width
, int height
)
822 wxASSERT_MSG( (m_widget
!= NULL
), wxT("invalid frame") );
825 width
+ m_miniEdge
*2, height
+ m_miniEdge
*2 + m_miniTitle
, 0);
828 void wxTopLevelWindowGTK::GtkOnSize( int WXUNUSED(x
), int WXUNUSED(y
),
829 int width
, int height
)
831 // due to a bug in gtk, x,y are always 0
836 if (m_resizing
) return;
839 if ( m_wxwindow
== NULL
) return;
844 /* wxMDIChildFrame derives from wxFrame but it _is_ a wxWindow as it uses
845 wxWindow::Create to create it's GTK equivalent. m_mainWidget is only
846 set in wxFrame::Create so it is used to check what kind of frame we
847 have here. if m_mainWidget is NULL it is a wxMDIChildFrame and so we
848 skip the part which handles m_frameMenuBar, m_frameToolBar and (most
849 importantly) m_mainWidget */
851 int minWidth
= GetMinWidth(),
852 minHeight
= GetMinHeight(),
853 maxWidth
= GetMaxWidth(),
854 maxHeight
= GetMaxHeight();
857 // GPE's window manager doesn't like size hints
858 // at all, esp. when the user has to use the
866 if ((minWidth
!= -1) && (m_width
< minWidth
)) m_width
= minWidth
;
867 if ((minHeight
!= -1) && (m_height
< minHeight
)) m_height
= minHeight
;
868 if ((maxWidth
!= -1) && (m_width
> maxWidth
)) m_width
= maxWidth
;
869 if ((maxHeight
!= -1) && (m_height
> maxHeight
)) m_height
= maxHeight
;
874 gint flag
= 0; // GDK_HINT_POS;
877 if ((minWidth
!= -1) || (minHeight
!= -1)) flag
|= GDK_HINT_MIN_SIZE
;
878 if ((maxWidth
!= -1) || (maxHeight
!= -1)) flag
|= GDK_HINT_MAX_SIZE
;
880 geom
.min_width
= minWidth
;
881 geom
.min_height
= minHeight
;
883 // Because of the way we set GDK_HINT_MAX_SIZE above, if either of
884 // maxHeight or maxWidth is set, we must set them both, else the
885 // remaining -1 will be taken literally.
887 // I'm certain this also happens elsewhere, and is the probable
888 // cause of other such things as:
889 // Gtk-WARNING **: gtk_widget_size_allocate():
890 // attempt to allocate widget with width 65535 and height 600
891 // but I don't have time to track them all now..
893 // Really we need to encapulate all this height/width business and
894 // stop any old method from ripping at the members directly and
895 // scattering -1's without regard for who might resolve them later.
897 geom
.max_width
= ( maxHeight
== -1 ) ? maxWidth
898 : ( maxWidth
== -1 ) ? wxGetDisplaySize().GetWidth()
901 geom
.max_height
= ( maxWidth
== -1 ) ? maxHeight
// ( == -1 here )
902 : ( maxHeight
== -1 ) ? wxGetDisplaySize().GetHeight()
905 gtk_window_set_geometry_hints( GTK_WINDOW(m_widget
),
908 (GdkWindowHints
) flag
);
910 /* I revert back to wxGTK's original behaviour. m_mainWidget holds the
911 * menubar, the toolbar and the client area, which is represented by
913 * this hurts in the eye, but I don't want to call SetSize()
914 * because I don't want to call any non-native functions here. */
916 int client_x
= m_miniEdge
;
917 int client_y
= m_miniEdge
+ m_miniTitle
;
918 int client_w
= m_width
- 2*m_miniEdge
;
919 int client_h
= m_height
- 2*m_miniEdge
- m_miniTitle
;
921 gtk_pizza_set_size( GTK_PIZZA(m_mainWidget
),
923 client_x
, client_y
, client_w
, client_h
);
927 // If there is no m_mainWidget between m_widget and m_wxwindow there
928 // is no need to set the size or position of m_wxwindow.
933 // send size event to frame
934 wxSizeEvent
event( wxSize(m_width
,m_height
), GetId() );
935 event
.SetEventObject( this );
936 GetEventHandler()->ProcessEvent( event
);
941 void wxTopLevelWindowGTK::OnInternalIdle()
943 if (!m_sizeSet
&& GTK_WIDGET_REALIZED(m_wxwindow
))
945 GtkOnSize( m_x
, m_y
, m_width
, m_height
);
947 // we'll come back later
949 wxapp_install_idle_handler();
953 // set the focus if not done yet and if we can already do it
954 if ( GTK_WIDGET_REALIZED(m_wxwindow
) )
956 if ( g_delayedFocus
&&
957 wxGetTopLevelParent((wxWindow
*)g_delayedFocus
) == this )
959 wxLogTrace(_T("focus"),
960 _T("Setting focus from wxTLW::OnIdle() to %s(%s)"),
961 g_delayedFocus
->GetClassInfo()->GetClassName(),
962 g_delayedFocus
->GetLabel().c_str());
964 g_delayedFocus
->SetFocus();
965 g_delayedFocus
= NULL
;
969 wxWindow::OnInternalIdle();
971 // Synthetize activate events.
972 if ( g_sendActivateEvent
!= -1 )
974 bool activate
= g_sendActivateEvent
!= 0;
976 // if (!activate) wxPrintf( wxT("de") );
977 // wxPrintf( wxT("activate\n") );
980 g_sendActivateEvent
= -1;
982 wxTheApp
->SetActive(activate
, (wxWindow
*)g_lastActiveFrame
);
986 // ----------------------------------------------------------------------------
988 // ----------------------------------------------------------------------------
990 void wxTopLevelWindowGTK::SetTitle( const wxString
&title
)
992 wxASSERT_MSG( (m_widget
!= NULL
), wxT("invalid frame") );
995 gtk_window_set_title( GTK_WINDOW(m_widget
), wxGTK_CONV( title
) );
998 void wxTopLevelWindowGTK::SetIcon( const wxIcon
&icon
)
1000 SetIcons( wxIconBundle( icon
) );
1003 void wxTopLevelWindowGTK::SetIcons( const wxIconBundle
&icons
)
1005 wxASSERT_MSG( (m_widget
!= NULL
), wxT("invalid frame") );
1007 wxTopLevelWindowBase::SetIcons( icons
);
1011 size_t max
= icons
.m_icons
.GetCount();
1013 for (size_t i
= 0; i
< max
; i
++)
1015 if (icons
.m_icons
[i
].Ok())
1017 list
= g_list_prepend(list
, icons
.m_icons
[i
].GetPixbuf());
1020 gtk_window_set_icon_list(GTK_WINDOW(m_widget
), list
);
1023 #else // !__WXGTK20__
1024 GdkWindow
* window
= m_widget
->window
;
1028 wxIcon icon
= icons
.GetIcon(-1);
1031 wxMask
*mask
= icon
.GetMask();
1032 GdkBitmap
*bm
= (GdkBitmap
*) NULL
;
1033 if (mask
) bm
= mask
->GetBitmap();
1035 gdk_window_set_icon( m_widget
->window
, (GdkWindow
*) NULL
, icon
.GetPixmap(), bm
);
1038 wxSetIconsX11( (WXDisplay
*)GDK_WINDOW_XDISPLAY( window
),
1039 (WXWindow
)GDK_WINDOW_XWINDOW( window
), icons
);
1040 #endif // !__WXGTK20__
1043 // ----------------------------------------------------------------------------
1044 // frame state: maximized/iconized/normal
1045 // ----------------------------------------------------------------------------
1047 void wxTopLevelWindowGTK::Maximize(bool maximize
)
1051 gtk_window_maximize( GTK_WINDOW( m_widget
) );
1053 gtk_window_unmaximize( GTK_WINDOW( m_widget
) );
1055 wxFAIL_MSG( _T("not implemented") );
1059 bool wxTopLevelWindowGTK::IsMaximized() const
1062 if(!m_widget
->window
)
1065 return gdk_window_get_state(m_widget
->window
) & GDK_WINDOW_STATE_MAXIMIZED
;
1067 // wxFAIL_MSG( _T("not implemented") );
1069 // This is an approximation
1074 void wxTopLevelWindowGTK::Restore()
1077 // "Present" seems similar enough to "restore"
1078 gtk_window_present( GTK_WINDOW( m_widget
) );
1080 wxFAIL_MSG( _T("not implemented") );
1084 void wxTopLevelWindowGTK::Iconize( bool iconize
)
1088 gtk_window_iconify( GTK_WINDOW( m_widget
) );
1090 gtk_window_deiconify( GTK_WINDOW( m_widget
) );
1094 GdkWindow
*window
= m_widget
->window
;
1096 // you should do it later, for example from OnCreate() handler
1097 wxCHECK_RET( window
, _T("frame not created yet - can't iconize") );
1099 XIconifyWindow( GDK_WINDOW_XDISPLAY( window
),
1100 GDK_WINDOW_XWINDOW( window
),
1101 DefaultScreen( GDK_DISPLAY() ) );
1106 bool wxTopLevelWindowGTK::IsIconized() const
1108 return m_isIconized
;
1111 void wxTopLevelWindowGTK::SetIconizeState(bool iconize
)
1113 if ( iconize
!= m_isIconized
)
1115 m_isIconized
= iconize
;
1116 (void)SendIconizeEvent(iconize
);
1120 void wxTopLevelWindowGTK::AddGrab()
1125 gtk_grab_add( m_widget
);
1127 gtk_grab_remove( m_widget
);
1131 void wxTopLevelWindowGTK::RemoveGrab()
1142 static bool do_shape_combine_region(GdkWindow
* window
, const wxRegion
& region
)
1146 if (region
.IsEmpty())
1148 gdk_window_shape_combine_mask(window
, NULL
, 0, 0);
1153 gdk_window_shape_combine_region(window
, region
.GetRegion(), 0, 0);
1155 wxBitmap bmp
= region
.ConvertToBitmap();
1156 bmp
.SetMask(new wxMask(bmp
, *wxBLACK
));
1157 GdkBitmap
* mask
= bmp
.GetMask()->GetBitmap();
1158 gdk_window_shape_combine_mask(window
, mask
, 0, 0);
1167 bool wxTopLevelWindowGTK::SetShape(const wxRegion
& region
)
1169 wxCHECK_MSG( HasFlag(wxFRAME_SHAPED
), FALSE
,
1170 _T("Shaped windows must be created with the wxFRAME_SHAPED style."));
1172 GdkWindow
*window
= NULL
;
1175 window
= GTK_PIZZA(m_wxwindow
)->bin_window
;
1176 do_shape_combine_region(window
, region
);
1178 window
= m_widget
->window
;
1179 return do_shape_combine_region(window
, region
);
1182 bool wxTopLevelWindowGTK::IsActive()
1184 return (this == (wxTopLevelWindowGTK
*)g_activeFrame
);