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())
230 gdk_window_get_root_origin( win
->m_widget
->window
, &x
, &y
);
234 wxMoveEvent
mevent( wxPoint(win
->m_x
,win
->m_y
), win
->GetId() );
235 mevent
.SetEventObject( win
);
236 win
->GetEventHandler()->ProcessEvent( mevent
);
241 //-----------------------------------------------------------------------------
242 // "realize" from m_widget
243 //-----------------------------------------------------------------------------
245 // we cannot MWM hints and icons before the widget has been realized,
246 // so we do this directly after realization
249 gtk_frame_realized_callback( GtkWidget
* WXUNUSED(widget
),
250 wxTopLevelWindowGTK
*win
)
253 wxapp_install_idle_handler();
255 // All this is for Motif Window Manager "hints" and is supposed to be
256 // recognized by other WM as well. Not tested.
257 gdk_window_set_decorations(win
->m_widget
->window
,
258 (GdkWMDecoration
)win
->m_gdkDecor
);
259 gdk_window_set_functions(win
->m_widget
->window
,
260 (GdkWMFunction
)win
->m_gdkFunc
);
262 // GTK's shrinking/growing policy
263 if ((win
->m_gdkFunc
& GDK_FUNC_RESIZE
) == 0)
264 gtk_window_set_policy(GTK_WINDOW(win
->m_widget
), 0, 0, 1);
266 gtk_window_set_policy(GTK_WINDOW(win
->m_widget
), 1, 1, 1);
269 wxIconBundle iconsOld
= win
->GetIcons();
270 if ( iconsOld
.GetIcon(-1).Ok() )
272 win
->SetIcon( wxNullIcon
);
273 win
->SetIcons( iconsOld
);
277 //-----------------------------------------------------------------------------
278 // "map_event" from m_widget
279 //-----------------------------------------------------------------------------
282 gtk_frame_map_callback( GtkWidget
* WXUNUSED(widget
),
283 GdkEvent
* WXUNUSED(event
),
284 wxTopLevelWindow
*win
)
286 win
->SetIconizeState(FALSE
);
289 //-----------------------------------------------------------------------------
290 // "unmap_event" from m_widget
291 //-----------------------------------------------------------------------------
294 gtk_frame_unmap_callback( GtkWidget
* WXUNUSED(widget
),
295 GdkEvent
* WXUNUSED(event
),
296 wxTopLevelWindow
*win
)
298 win
->SetIconizeState(TRUE
);
301 //-----------------------------------------------------------------------------
302 // "expose_event" of m_client
303 //-----------------------------------------------------------------------------
305 static int gtk_window_expose_callback( GtkWidget
*widget
, GdkEventExpose
*gdk_event
, wxWindow
*win
)
307 GtkPizza
*pizza
= GTK_PIZZA(widget
);
309 gtk_paint_flat_box (win
->m_widget
->style
,
310 pizza
->bin_window
, GTK_STATE_NORMAL
,
320 //-----------------------------------------------------------------------------
321 // "draw" of m_client
322 //-----------------------------------------------------------------------------
326 static void gtk_window_draw_callback( GtkWidget
*widget
, GdkRectangle
*rect
, wxWindow
*win
)
328 GtkPizza
*pizza
= GTK_PIZZA(widget
);
330 gtk_paint_flat_box (win
->m_widget
->style
,
331 pizza
->bin_window
, GTK_STATE_NORMAL
,
341 // ----------------------------------------------------------------------------
342 // wxTopLevelWindowGTK itself
343 // ----------------------------------------------------------------------------
345 //-----------------------------------------------------------------------------
346 // InsertChild for wxTopLevelWindowGTK
347 //-----------------------------------------------------------------------------
349 /* Callback for wxTopLevelWindowGTK. This very strange beast has to be used because
350 * C++ has no virtual methods in a constructor. We have to emulate a
351 * virtual function here as wxWidgets requires different ways to insert
352 * a child in container classes. */
354 static void wxInsertChildInTopLevelWindow( wxTopLevelWindowGTK
* parent
, wxWindow
* child
)
356 wxASSERT( GTK_IS_WIDGET(child
->m_widget
) );
358 if (!parent
->m_insertInClientArea
)
360 // these are outside the client area
361 wxTopLevelWindowGTK
* frame
= (wxTopLevelWindowGTK
*) parent
;
362 gtk_pizza_put( GTK_PIZZA(frame
->m_mainWidget
),
363 GTK_WIDGET(child
->m_widget
),
371 // these are inside the client area
372 gtk_pizza_put( GTK_PIZZA(parent
->m_wxwindow
),
373 GTK_WIDGET(child
->m_widget
),
380 // resize on OnInternalIdle
381 parent
->GtkUpdateSize();
384 // ----------------------------------------------------------------------------
385 // wxTopLevelWindowGTK creation
386 // ----------------------------------------------------------------------------
388 void wxTopLevelWindowGTK::Init()
393 m_mainWidget
= (GtkWidget
*) NULL
;
394 m_insertInClientArea
= TRUE
;
395 m_isIconized
= FALSE
;
396 m_fsIsShowing
= FALSE
;
397 m_themeEnabled
= TRUE
;
398 m_gdkDecor
= m_gdkFunc
= 0;
402 bool wxTopLevelWindowGTK::Create( wxWindow
*parent
,
404 const wxString
& title
,
406 const wxSize
& sizeOrig
,
408 const wxString
&name
)
410 // always create a frame of some reasonable, even if arbitrary, size (at
411 // least for MSW compatibility)
412 wxSize size
= sizeOrig
;
413 size
.x
= WidthDefault(size
.x
);
414 size
.y
= HeightDefault(size
.y
);
416 wxTopLevelWindows
.Append( this );
418 m_needParent
= FALSE
;
420 if (!PreCreation( parent
, pos
, size
) ||
421 !CreateBase( parent
, id
, pos
, size
, style
, wxDefaultValidator
, name
))
423 wxFAIL_MSG( wxT("wxTopLevelWindowGTK creation failed") );
429 m_insertCallback
= (wxInsertChildFunction
) wxInsertChildInTopLevelWindow
;
431 // NB: m_widget may be !=NULL if it was created by derived class' Create,
432 // e.g. in wxTaskBarIconAreaGTK
433 if (m_widget
== NULL
)
435 if (GetExtraStyle() & wxTOPLEVEL_EX_DIALOG
)
438 m_widget
= gtk_window_new(GTK_WINDOW_TOPLEVEL
);
439 // Tell WM that this is a dialog window and make it center
440 // on parent by default (this is what GtkDialog ctor does):
441 gtk_window_set_type_hint(GTK_WINDOW(m_widget
),
442 GDK_WINDOW_TYPE_HINT_DIALOG
);
443 gtk_window_set_position(GTK_WINDOW(m_widget
),
444 GTK_WIN_POS_CENTER_ON_PARENT
);
446 m_widget
= gtk_window_new(GTK_WINDOW_DIALOG
);
451 m_widget
= gtk_window_new(GTK_WINDOW_TOPLEVEL
);
452 #if GTK_CHECK_VERSION(2,1,0)
453 if (style
& wxFRAME_TOOL_WINDOW
)
454 gtk_window_set_type_hint(GTK_WINDOW(m_widget
),
455 GDK_WINDOW_TYPE_HINT_UTILITY
);
461 wxWindow
*topParent
= wxGetTopLevelParent(m_parent
);
462 if (topParent
&& (((GTK_IS_WINDOW(topParent
->m_widget
)) &&
463 (GetExtraStyle() & wxTOPLEVEL_EX_DIALOG
)) ||
464 (style
& wxFRAME_FLOAT_ON_PARENT
)))
466 gtk_window_set_transient_for( GTK_WINDOW(m_widget
),
467 GTK_WINDOW(topParent
->m_widget
) );
470 #if GTK_CHECK_VERSION(2,2,0)
471 if (style
& wxFRAME_NO_TASKBAR
)
473 gtk_window_set_skip_taskbar_hint(GTK_WINDOW(m_widget
), TRUE
);
478 gtk_window_set_wmclass( GTK_WINDOW(m_widget
), wxGTK_CONV( name
), wxGTK_CONV( name
) );
480 gtk_window_set_title( GTK_WINDOW(m_widget
), wxGTK_CONV( title
) );
481 GTK_WIDGET_UNSET_FLAGS( m_widget
, GTK_CAN_FOCUS
);
483 gtk_signal_connect( GTK_OBJECT(m_widget
), "delete_event",
484 GTK_SIGNAL_FUNC(gtk_frame_delete_callback
), (gpointer
)this );
486 // m_mainWidget holds the toolbar, the menubar and the client area
487 m_mainWidget
= gtk_pizza_new();
488 gtk_widget_show( m_mainWidget
);
489 GTK_WIDGET_UNSET_FLAGS( m_mainWidget
, GTK_CAN_FOCUS
);
490 gtk_container_add( GTK_CONTAINER(m_widget
), m_mainWidget
);
492 if (m_miniEdge
== 0) // wxMiniFrame has its own version.
494 // For m_mainWidget themes
495 gtk_signal_connect( GTK_OBJECT(m_mainWidget
), "expose_event",
496 GTK_SIGNAL_FUNC(gtk_window_expose_callback
), (gpointer
)this );
498 gtk_signal_connect( GTK_OBJECT(m_mainWidget
), "draw",
499 GTK_SIGNAL_FUNC(gtk_window_draw_callback
), (gpointer
)this );
503 // m_wxwindow only represents the client area without toolbar and menubar
504 m_wxwindow
= gtk_pizza_new();
505 gtk_widget_show( m_wxwindow
);
506 gtk_container_add( GTK_CONTAINER(m_mainWidget
), m_wxwindow
);
508 // we donm't allow the frame to get the focus as otherwise
509 // the frame will grab it at arbitrary focus changes
510 GTK_WIDGET_UNSET_FLAGS( m_wxwindow
, GTK_CAN_FOCUS
);
512 if (m_parent
) m_parent
->AddChild( this );
514 // the user resized the frame by dragging etc.
515 gtk_signal_connect( GTK_OBJECT(m_widget
), "size_allocate",
516 GTK_SIGNAL_FUNC(gtk_frame_size_callback
), (gpointer
)this );
520 if ((m_x
!= -1) || (m_y
!= -1))
521 gtk_widget_set_uposition( m_widget
, m_x
, m_y
);
523 gtk_window_set_default_size( GTK_WINDOW(m_widget
), m_width
, m_height
);
525 // we cannot set MWM hints and icons before the widget has
526 // been realized, so we do this directly after realization
527 gtk_signal_connect( GTK_OBJECT(m_widget
), "realize",
528 GTK_SIGNAL_FUNC(gtk_frame_realized_callback
), (gpointer
) this );
530 // the only way to get the window size is to connect to this event
531 gtk_signal_connect( GTK_OBJECT(m_widget
), "configure_event",
532 GTK_SIGNAL_FUNC(gtk_frame_configure_callback
), (gpointer
)this );
534 // map and unmap for iconized state
535 gtk_signal_connect( GTK_OBJECT(m_widget
), "map_event",
536 GTK_SIGNAL_FUNC(gtk_frame_map_callback
), (gpointer
)this );
537 gtk_signal_connect( GTK_OBJECT(m_widget
), "unmap_event",
538 GTK_SIGNAL_FUNC(gtk_frame_unmap_callback
), (gpointer
)this );
540 // the only way to get the window size is to connect to this event
541 gtk_signal_connect( GTK_OBJECT(m_widget
), "configure_event",
542 GTK_SIGNAL_FUNC(gtk_frame_configure_callback
), (gpointer
)this );
544 // disable native tab traversal
545 gtk_signal_connect( GTK_OBJECT(m_widget
), "focus",
546 GTK_SIGNAL_FUNC(gtk_frame_focus_callback
), (gpointer
)this );
549 gtk_signal_connect( GTK_OBJECT(m_widget
), "focus_in_event",
550 GTK_SIGNAL_FUNC(gtk_frame_focus_in_callback
), (gpointer
)this );
551 gtk_signal_connect( GTK_OBJECT(m_widget
), "focus_out_event",
552 GTK_SIGNAL_FUNC(gtk_frame_focus_out_callback
), (gpointer
)this );
555 if ((m_miniEdge
> 0) || (style
& wxSIMPLE_BORDER
) || (style
& wxNO_BORDER
))
562 m_gdkDecor
= (long) GDK_DECOR_BORDER
;
563 m_gdkFunc
= (long) GDK_FUNC_MOVE
;
565 // All this is for Motif Window Manager "hints" and is supposed to be
566 // recognized by other WMs as well.
567 if ((style
& wxCAPTION
) != 0)
569 m_gdkDecor
|= GDK_DECOR_TITLE
;
571 if ((style
& wxCLOSE_BOX
) != 0)
573 m_gdkFunc
|= GDK_FUNC_CLOSE
;
575 if ((style
& wxSYSTEM_MENU
) != 0)
577 m_gdkDecor
|= GDK_DECOR_MENU
;
579 if ((style
& wxMINIMIZE_BOX
) != 0)
581 m_gdkFunc
|= GDK_FUNC_MINIMIZE
;
582 m_gdkDecor
|= GDK_DECOR_MINIMIZE
;
584 if ((style
& wxMAXIMIZE_BOX
) != 0)
586 m_gdkFunc
|= GDK_FUNC_MAXIMIZE
;
587 m_gdkDecor
|= GDK_DECOR_MAXIMIZE
;
589 if ((style
& wxRESIZE_BORDER
) != 0)
591 m_gdkFunc
|= GDK_FUNC_RESIZE
;
592 m_gdkDecor
|= GDK_DECOR_RESIZEH
;
599 wxTopLevelWindowGTK::~wxTopLevelWindowGTK()
603 wxASSERT_MSG( FALSE
, _T("Window still grabbed"));
607 m_isBeingDeleted
= TRUE
;
609 // it may also be GtkScrolledWindow in the case of an MDI child
610 if (GTK_IS_WINDOW(m_widget
))
612 gtk_window_set_focus( GTK_WINDOW(m_widget
), NULL
);
615 if (g_activeFrame
== this)
616 g_activeFrame
= NULL
;
617 if (g_lastActiveFrame
== this)
618 g_lastActiveFrame
= NULL
;
623 bool wxTopLevelWindowGTK::ShowFullScreen(bool show
, long style
)
625 if (show
== m_fsIsShowing
)
626 return FALSE
; // return what?
628 m_fsIsShowing
= show
;
630 wxX11FullScreenMethod method
=
631 wxGetFullScreenMethodX11((WXDisplay
*)GDK_DISPLAY(),
632 (WXWindow
)GDK_ROOT_WINDOW());
634 #if GTK_CHECK_VERSION(2,2,0)
635 // NB: gtk_window_fullscreen() uses freedesktop.org's WMspec extensions
636 // to switch to fullscreen, which is not always available. We must
637 // check if WM supports the spec and use legacy methods if it
639 if (method
== wxX11_FS_WMSPEC
)
642 gtk_window_fullscreen( GTK_WINDOW( m_widget
) );
644 gtk_window_unfullscreen( GTK_WINDOW( m_widget
) );
649 #endif // GTK+ >= 2.2.0
651 GdkWindow
*window
= m_widget
->window
;
655 m_fsSaveFlag
= style
;
656 GetPosition( &m_fsSaveFrame
.x
, &m_fsSaveFrame
.y
);
657 GetSize( &m_fsSaveFrame
.width
, &m_fsSaveFrame
.height
);
659 int screen_width
,screen_height
;
660 wxDisplaySize( &screen_width
, &screen_height
);
662 gint client_x
, client_y
, root_x
, root_y
;
665 if (method
!= wxX11_FS_WMSPEC
)
667 // don't do it always, Metacity hates it
668 m_fsSaveGdkFunc
= m_gdkFunc
;
669 m_fsSaveGdkDecor
= m_gdkDecor
;
670 m_gdkFunc
= m_gdkDecor
= 0;
671 gdk_window_set_decorations(window
, (GdkWMDecoration
)0);
672 gdk_window_set_functions(window
, (GdkWMFunction
)0);
675 gdk_window_get_origin (m_widget
->window
, &root_x
, &root_y
);
676 gdk_window_get_geometry (m_widget
->window
, &client_x
, &client_y
,
677 &width
, &height
, NULL
);
679 gdk_window_move_resize (m_widget
->window
, -client_x
, -client_y
,
680 screen_width
+ 1, screen_height
+ 1);
682 wxSetFullScreenStateX11((WXDisplay
*)GDK_DISPLAY(),
683 (WXWindow
)GDK_ROOT_WINDOW(),
684 (WXWindow
)GDK_WINDOW_XWINDOW(window
),
685 show
, &m_fsSaveFrame
, method
);
689 if (method
!= wxX11_FS_WMSPEC
)
691 // don't do it always, Metacity hates it
692 m_gdkFunc
= m_fsSaveGdkFunc
;
693 m_gdkDecor
= m_fsSaveGdkDecor
;
694 gdk_window_set_decorations(window
, (GdkWMDecoration
)m_gdkDecor
);
695 gdk_window_set_functions(window
, (GdkWMFunction
)m_gdkFunc
);
698 wxSetFullScreenStateX11((WXDisplay
*)GDK_DISPLAY(),
699 (WXWindow
)GDK_ROOT_WINDOW(),
700 (WXWindow
)GDK_WINDOW_XWINDOW(window
),
701 show
, &m_fsSaveFrame
, method
);
703 SetSize(m_fsSaveFrame
.x
, m_fsSaveFrame
.y
,
704 m_fsSaveFrame
.width
, m_fsSaveFrame
.height
);
711 // ----------------------------------------------------------------------------
712 // overridden wxWindow methods
713 // ----------------------------------------------------------------------------
715 bool wxTopLevelWindowGTK::Show( bool show
)
717 wxASSERT_MSG( (m_widget
!= NULL
), wxT("invalid frame") );
719 if (show
&& !m_sizeSet
)
721 /* by calling GtkOnSize here, we don't have to call
722 either after showing the frame, which would entail
723 much ugly flicker or from within the size_allocate
724 handler, because GTK 1.1.X forbids that. */
726 GtkOnSize( m_x
, m_y
, m_width
, m_height
);
730 gtk_widget_set_uposition( m_widget
, m_x
, m_y
);
732 return wxWindow::Show( show
);
735 void wxTopLevelWindowGTK::DoMoveWindow(int WXUNUSED(x
), int WXUNUSED(y
), int WXUNUSED(width
), int WXUNUSED(height
) )
737 wxFAIL_MSG( wxT("DoMoveWindow called for wxTopLevelWindowGTK") );
740 void wxTopLevelWindowGTK::DoSetSize( int x
, int y
, int width
, int height
, int sizeFlags
)
742 wxASSERT_MSG( (m_widget
!= NULL
), wxT("invalid frame") );
744 // this shouldn't happen: wxFrame, wxMDIParentFrame and wxMDIChildFrame have m_wxwindow
745 wxASSERT_MSG( (m_wxwindow
!= NULL
), wxT("invalid frame") );
755 int old_width
= m_width
;
756 int old_height
= m_height
;
758 if ((sizeFlags
& wxSIZE_ALLOW_MINUS_ONE
) == 0)
760 if (x
!= -1) m_x
= x
;
761 if (y
!= -1) m_y
= y
;
768 if (width
!= -1) m_width
= width
;
769 if (height
!= -1) m_height
= height
;
772 if ((sizeFlags & wxSIZE_AUTO_WIDTH) == wxSIZE_AUTO_WIDTH)
774 if (width == -1) m_width = 80;
777 if ((sizeFlags & wxSIZE_AUTO_HEIGHT) == wxSIZE_AUTO_HEIGHT)
779 if (height == -1) m_height = 26;
783 int minWidth
= GetMinWidth(),
784 minHeight
= GetMinHeight(),
785 maxWidth
= GetMaxWidth(),
786 maxHeight
= GetMaxHeight();
789 // GPE's window manager doesn't like size hints
790 // at all, esp. when the user has to use the
798 if ((minWidth
!= -1) && (m_width
< minWidth
)) m_width
= minWidth
;
799 if ((minHeight
!= -1) && (m_height
< minHeight
)) m_height
= minHeight
;
800 if ((maxWidth
!= -1) && (m_width
> maxWidth
)) m_width
= maxWidth
;
801 if ((maxHeight
!= -1) && (m_height
> maxHeight
)) m_height
= maxHeight
;
803 if ((m_x
!= -1) || (m_y
!= -1))
805 if ((m_x
!= old_x
) || (m_y
!= old_y
))
807 gtk_widget_set_uposition( m_widget
, m_x
, m_y
);
811 if ((m_width
!= old_width
) || (m_height
!= old_height
))
813 if (m_widget
->window
)
814 gdk_window_resize( m_widget
->window
, m_width
, m_height
);
816 gtk_window_set_default_size( GTK_WINDOW(m_widget
), m_width
, m_height
);
818 /* we set the size in GtkOnSize, i.e. mostly the actual resizing is
819 done either directly before the frame is shown or in idle time
820 so that different calls to SetSize() don't lead to flicker. */
827 void wxTopLevelWindowGTK::DoGetClientSize( int *width
, int *height
) const
829 wxASSERT_MSG( (m_widget
!= NULL
), wxT("invalid frame") );
831 wxWindow::DoGetClientSize( width
, height
);
835 *height
-= m_miniEdge
*2 + m_miniTitle
;
839 *width
-= m_miniEdge
*2;
843 void wxTopLevelWindowGTK::DoSetClientSize( int width
, int height
)
845 wxASSERT_MSG( (m_widget
!= NULL
), wxT("invalid frame") );
848 width
+ m_miniEdge
*2, height
+ m_miniEdge
*2 + m_miniTitle
, 0);
851 void wxTopLevelWindowGTK::GtkOnSize( int WXUNUSED(x
), int WXUNUSED(y
),
852 int width
, int height
)
854 // due to a bug in gtk, x,y are always 0
859 if (m_resizing
) return;
862 if ( m_wxwindow
== NULL
) return;
867 /* wxMDIChildFrame derives from wxFrame but it _is_ a wxWindow as it uses
868 wxWindow::Create to create it's GTK equivalent. m_mainWidget is only
869 set in wxFrame::Create so it is used to check what kind of frame we
870 have here. if m_mainWidget is NULL it is a wxMDIChildFrame and so we
871 skip the part which handles m_frameMenuBar, m_frameToolBar and (most
872 importantly) m_mainWidget */
874 int minWidth
= GetMinWidth(),
875 minHeight
= GetMinHeight(),
876 maxWidth
= GetMaxWidth(),
877 maxHeight
= GetMaxHeight();
880 // GPE's window manager doesn't like size hints
881 // at all, esp. when the user has to use the
889 if ((minWidth
!= -1) && (m_width
< minWidth
)) m_width
= minWidth
;
890 if ((minHeight
!= -1) && (m_height
< minHeight
)) m_height
= minHeight
;
891 if ((maxWidth
!= -1) && (m_width
> maxWidth
)) m_width
= maxWidth
;
892 if ((maxHeight
!= -1) && (m_height
> maxHeight
)) m_height
= maxHeight
;
897 gint flag
= 0; // GDK_HINT_POS;
900 if ((minWidth
!= -1) || (minHeight
!= -1)) flag
|= GDK_HINT_MIN_SIZE
;
901 if ((maxWidth
!= -1) || (maxHeight
!= -1)) flag
|= GDK_HINT_MAX_SIZE
;
903 geom
.min_width
= minWidth
;
904 geom
.min_height
= minHeight
;
906 // Because of the way we set GDK_HINT_MAX_SIZE above, if either of
907 // maxHeight or maxWidth is set, we must set them both, else the
908 // remaining -1 will be taken literally.
910 // I'm certain this also happens elsewhere, and is the probable
911 // cause of other such things as:
912 // Gtk-WARNING **: gtk_widget_size_allocate():
913 // attempt to allocate widget with width 65535 and height 600
914 // but I don't have time to track them all now..
916 // Really we need to encapulate all this height/width business and
917 // stop any old method from ripping at the members directly and
918 // scattering -1's without regard for who might resolve them later.
920 geom
.max_width
= ( maxHeight
== -1 ) ? maxWidth
921 : ( maxWidth
== -1 ) ? wxGetDisplaySize().GetWidth()
924 geom
.max_height
= ( maxWidth
== -1 ) ? maxHeight
// ( == -1 here )
925 : ( maxHeight
== -1 ) ? wxGetDisplaySize().GetHeight()
928 gtk_window_set_geometry_hints( GTK_WINDOW(m_widget
),
931 (GdkWindowHints
) flag
);
933 /* I revert back to wxGTK's original behaviour. m_mainWidget holds the
934 * menubar, the toolbar and the client area, which is represented by
936 * this hurts in the eye, but I don't want to call SetSize()
937 * because I don't want to call any non-native functions here. */
939 int client_x
= m_miniEdge
;
940 int client_y
= m_miniEdge
+ m_miniTitle
;
941 int client_w
= m_width
- 2*m_miniEdge
;
942 int client_h
= m_height
- 2*m_miniEdge
- m_miniTitle
;
944 gtk_pizza_set_size( GTK_PIZZA(m_mainWidget
),
946 client_x
, client_y
, client_w
, client_h
);
950 // If there is no m_mainWidget between m_widget and m_wxwindow there
951 // is no need to set the size or position of m_wxwindow.
956 // send size event to frame
957 wxSizeEvent
event( wxSize(m_width
,m_height
), GetId() );
958 event
.SetEventObject( this );
959 GetEventHandler()->ProcessEvent( event
);
964 void wxTopLevelWindowGTK::OnInternalIdle()
966 if (!m_sizeSet
&& GTK_WIDGET_REALIZED(m_wxwindow
))
968 GtkOnSize( m_x
, m_y
, m_width
, m_height
);
970 // we'll come back later
972 wxapp_install_idle_handler();
976 // set the focus if not done yet and if we can already do it
977 if ( GTK_WIDGET_REALIZED(m_wxwindow
) )
979 if ( g_delayedFocus
&&
980 wxGetTopLevelParent((wxWindow
*)g_delayedFocus
) == this )
982 wxLogTrace(_T("focus"),
983 _T("Setting focus from wxTLW::OnIdle() to %s(%s)"),
984 g_delayedFocus
->GetClassInfo()->GetClassName(),
985 g_delayedFocus
->GetLabel().c_str());
987 g_delayedFocus
->SetFocus();
988 g_delayedFocus
= NULL
;
992 wxWindow::OnInternalIdle();
994 // Synthetize activate events.
995 if ( g_sendActivateEvent
!= -1 )
997 bool activate
= g_sendActivateEvent
!= 0;
999 // if (!activate) wxPrintf( wxT("de") );
1000 // wxPrintf( wxT("activate\n") );
1003 g_sendActivateEvent
= -1;
1005 wxTheApp
->SetActive(activate
, (wxWindow
*)g_lastActiveFrame
);
1009 // ----------------------------------------------------------------------------
1011 // ----------------------------------------------------------------------------
1013 void wxTopLevelWindowGTK::SetTitle( const wxString
&title
)
1015 wxASSERT_MSG( (m_widget
!= NULL
), wxT("invalid frame") );
1018 gtk_window_set_title( GTK_WINDOW(m_widget
), wxGTK_CONV( title
) );
1021 void wxTopLevelWindowGTK::SetIcon( const wxIcon
&icon
)
1023 SetIcons( wxIconBundle( icon
) );
1026 void wxTopLevelWindowGTK::SetIcons( const wxIconBundle
&icons
)
1028 wxASSERT_MSG( (m_widget
!= NULL
), wxT("invalid frame") );
1030 wxTopLevelWindowBase::SetIcons( icons
);
1034 size_t max
= icons
.m_icons
.GetCount();
1036 for (size_t i
= 0; i
< max
; i
++)
1038 if (icons
.m_icons
[i
].Ok())
1040 list
= g_list_prepend(list
, icons
.m_icons
[i
].GetPixbuf());
1043 gtk_window_set_icon_list(GTK_WINDOW(m_widget
), list
);
1046 #else // !__WXGTK20__
1047 GdkWindow
* window
= m_widget
->window
;
1051 wxIcon icon
= icons
.GetIcon(-1);
1054 wxMask
*mask
= icon
.GetMask();
1055 GdkBitmap
*bm
= (GdkBitmap
*) NULL
;
1056 if (mask
) bm
= mask
->GetBitmap();
1058 gdk_window_set_icon( m_widget
->window
, (GdkWindow
*) NULL
, icon
.GetPixmap(), bm
);
1061 wxSetIconsX11( (WXDisplay
*)GDK_WINDOW_XDISPLAY( window
),
1062 (WXWindow
)GDK_WINDOW_XWINDOW( window
), icons
);
1063 #endif // !__WXGTK20__
1066 // ----------------------------------------------------------------------------
1067 // frame state: maximized/iconized/normal
1068 // ----------------------------------------------------------------------------
1070 void wxTopLevelWindowGTK::Maximize(bool maximize
)
1074 gtk_window_maximize( GTK_WINDOW( m_widget
) );
1076 gtk_window_unmaximize( GTK_WINDOW( m_widget
) );
1078 wxFAIL_MSG( _T("not implemented") );
1082 bool wxTopLevelWindowGTK::IsMaximized() const
1085 if(!m_widget
->window
)
1088 return gdk_window_get_state(m_widget
->window
) & GDK_WINDOW_STATE_MAXIMIZED
;
1090 // wxFAIL_MSG( _T("not implemented") );
1092 // This is an approximation
1097 void wxTopLevelWindowGTK::Restore()
1100 // "Present" seems similar enough to "restore"
1101 gtk_window_present( GTK_WINDOW( m_widget
) );
1103 wxFAIL_MSG( _T("not implemented") );
1107 void wxTopLevelWindowGTK::Iconize( bool iconize
)
1111 gtk_window_iconify( GTK_WINDOW( m_widget
) );
1113 gtk_window_deiconify( GTK_WINDOW( m_widget
) );
1117 GdkWindow
*window
= m_widget
->window
;
1119 // you should do it later, for example from OnCreate() handler
1120 wxCHECK_RET( window
, _T("frame not created yet - can't iconize") );
1122 XIconifyWindow( GDK_WINDOW_XDISPLAY( window
),
1123 GDK_WINDOW_XWINDOW( window
),
1124 DefaultScreen( GDK_DISPLAY() ) );
1129 bool wxTopLevelWindowGTK::IsIconized() const
1131 return m_isIconized
;
1134 void wxTopLevelWindowGTK::SetIconizeState(bool iconize
)
1136 if ( iconize
!= m_isIconized
)
1138 m_isIconized
= iconize
;
1139 (void)SendIconizeEvent(iconize
);
1143 void wxTopLevelWindowGTK::AddGrab()
1148 gtk_grab_add( m_widget
);
1150 gtk_grab_remove( m_widget
);
1154 void wxTopLevelWindowGTK::RemoveGrab()
1165 static bool do_shape_combine_region(GdkWindow
* window
, const wxRegion
& region
)
1169 if (region
.IsEmpty())
1171 gdk_window_shape_combine_mask(window
, NULL
, 0, 0);
1176 gdk_window_shape_combine_region(window
, region
.GetRegion(), 0, 0);
1178 wxBitmap bmp
= region
.ConvertToBitmap();
1179 bmp
.SetMask(new wxMask(bmp
, *wxBLACK
));
1180 GdkBitmap
* mask
= bmp
.GetMask()->GetBitmap();
1181 gdk_window_shape_combine_mask(window
, mask
, 0, 0);
1190 bool wxTopLevelWindowGTK::SetShape(const wxRegion
& region
)
1192 wxCHECK_MSG( HasFlag(wxFRAME_SHAPED
), FALSE
,
1193 _T("Shaped windows must be created with the wxFRAME_SHAPED style."));
1195 GdkWindow
*window
= NULL
;
1198 window
= GTK_PIZZA(m_wxwindow
)->bin_window
;
1199 do_shape_combine_region(window
, region
);
1201 window
= m_widget
->window
;
1202 return do_shape_combine_region(window
, region
);
1205 bool wxTopLevelWindowGTK::IsActive()
1207 return (this == (wxTopLevelWindowGTK
*)g_activeFrame
);