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
)
455 gtk_window_set_type_hint(GTK_WINDOW(m_widget
),
456 GDK_WINDOW_TYPE_HINT_UTILITY
);
458 // On some WMs, like KDE, a TOOL_WINDOW will still show
459 // on the taskbar, but on Gnome a TOOL_WINDOW will not.
460 // For consistency between WMs and with Windows, we
461 // should set the NO_TASKBAR flag which will apply
462 // the set_skip_taskbar_hint if it is available,
463 // ensuring no taskbar entry will appear.
464 style
|= wxFRAME_NO_TASKBAR
;
471 wxWindow
*topParent
= wxGetTopLevelParent(m_parent
);
472 if (topParent
&& (((GTK_IS_WINDOW(topParent
->m_widget
)) &&
473 (GetExtraStyle() & wxTOPLEVEL_EX_DIALOG
)) ||
474 (style
& wxFRAME_FLOAT_ON_PARENT
)))
476 gtk_window_set_transient_for( GTK_WINDOW(m_widget
),
477 GTK_WINDOW(topParent
->m_widget
) );
480 #if GTK_CHECK_VERSION(2,2,0)
481 if (style
& wxFRAME_NO_TASKBAR
)
483 gtk_window_set_skip_taskbar_hint(GTK_WINDOW(m_widget
), TRUE
);
488 gtk_window_set_wmclass( GTK_WINDOW(m_widget
), wxGTK_CONV( name
), wxGTK_CONV( name
) );
490 gtk_window_set_title( GTK_WINDOW(m_widget
), wxGTK_CONV( title
) );
491 GTK_WIDGET_UNSET_FLAGS( m_widget
, GTK_CAN_FOCUS
);
493 gtk_signal_connect( GTK_OBJECT(m_widget
), "delete_event",
494 GTK_SIGNAL_FUNC(gtk_frame_delete_callback
), (gpointer
)this );
496 // m_mainWidget holds the toolbar, the menubar and the client area
497 m_mainWidget
= gtk_pizza_new();
498 gtk_widget_show( m_mainWidget
);
499 GTK_WIDGET_UNSET_FLAGS( m_mainWidget
, GTK_CAN_FOCUS
);
500 gtk_container_add( GTK_CONTAINER(m_widget
), m_mainWidget
);
502 if (m_miniEdge
== 0) // wxMiniFrame has its own version.
504 // For m_mainWidget themes
505 gtk_signal_connect( GTK_OBJECT(m_mainWidget
), "expose_event",
506 GTK_SIGNAL_FUNC(gtk_window_expose_callback
), (gpointer
)this );
508 gtk_signal_connect( GTK_OBJECT(m_mainWidget
), "draw",
509 GTK_SIGNAL_FUNC(gtk_window_draw_callback
), (gpointer
)this );
513 // m_wxwindow only represents the client area without toolbar and menubar
514 m_wxwindow
= gtk_pizza_new();
515 gtk_widget_show( m_wxwindow
);
516 gtk_container_add( GTK_CONTAINER(m_mainWidget
), m_wxwindow
);
518 // we donm't allow the frame to get the focus as otherwise
519 // the frame will grab it at arbitrary focus changes
520 GTK_WIDGET_UNSET_FLAGS( m_wxwindow
, GTK_CAN_FOCUS
);
522 if (m_parent
) m_parent
->AddChild( this );
524 // the user resized the frame by dragging etc.
525 gtk_signal_connect( GTK_OBJECT(m_widget
), "size_allocate",
526 GTK_SIGNAL_FUNC(gtk_frame_size_callback
), (gpointer
)this );
530 if ((m_x
!= -1) || (m_y
!= -1))
531 gtk_widget_set_uposition( m_widget
, m_x
, m_y
);
533 gtk_window_set_default_size( GTK_WINDOW(m_widget
), m_width
, m_height
);
535 // we cannot set MWM hints and icons before the widget has
536 // been realized, so we do this directly after realization
537 gtk_signal_connect( GTK_OBJECT(m_widget
), "realize",
538 GTK_SIGNAL_FUNC(gtk_frame_realized_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 // map and unmap for iconized state
545 gtk_signal_connect( GTK_OBJECT(m_widget
), "map_event",
546 GTK_SIGNAL_FUNC(gtk_frame_map_callback
), (gpointer
)this );
547 gtk_signal_connect( GTK_OBJECT(m_widget
), "unmap_event",
548 GTK_SIGNAL_FUNC(gtk_frame_unmap_callback
), (gpointer
)this );
550 // the only way to get the window size is to connect to this event
551 gtk_signal_connect( GTK_OBJECT(m_widget
), "configure_event",
552 GTK_SIGNAL_FUNC(gtk_frame_configure_callback
), (gpointer
)this );
554 // disable native tab traversal
555 gtk_signal_connect( GTK_OBJECT(m_widget
), "focus",
556 GTK_SIGNAL_FUNC(gtk_frame_focus_callback
), (gpointer
)this );
559 gtk_signal_connect( GTK_OBJECT(m_widget
), "focus_in_event",
560 GTK_SIGNAL_FUNC(gtk_frame_focus_in_callback
), (gpointer
)this );
561 gtk_signal_connect( GTK_OBJECT(m_widget
), "focus_out_event",
562 GTK_SIGNAL_FUNC(gtk_frame_focus_out_callback
), (gpointer
)this );
565 if ((m_miniEdge
> 0) || (style
& wxSIMPLE_BORDER
) || (style
& wxNO_BORDER
))
572 m_gdkDecor
= (long) GDK_DECOR_BORDER
;
573 m_gdkFunc
= (long) GDK_FUNC_MOVE
;
575 // All this is for Motif Window Manager "hints" and is supposed to be
576 // recognized by other WMs as well.
577 if ((style
& wxCAPTION
) != 0)
579 m_gdkDecor
|= GDK_DECOR_TITLE
;
581 if ((style
& wxCLOSE_BOX
) != 0)
583 m_gdkFunc
|= GDK_FUNC_CLOSE
;
585 if ((style
& wxSYSTEM_MENU
) != 0)
587 m_gdkDecor
|= GDK_DECOR_MENU
;
589 if ((style
& wxMINIMIZE_BOX
) != 0)
591 m_gdkFunc
|= GDK_FUNC_MINIMIZE
;
592 m_gdkDecor
|= GDK_DECOR_MINIMIZE
;
594 if ((style
& wxMAXIMIZE_BOX
) != 0)
596 m_gdkFunc
|= GDK_FUNC_MAXIMIZE
;
597 m_gdkDecor
|= GDK_DECOR_MAXIMIZE
;
599 if ((style
& wxRESIZE_BORDER
) != 0)
601 m_gdkFunc
|= GDK_FUNC_RESIZE
;
602 m_gdkDecor
|= GDK_DECOR_RESIZEH
;
609 wxTopLevelWindowGTK::~wxTopLevelWindowGTK()
613 wxASSERT_MSG( FALSE
, _T("Window still grabbed"));
617 m_isBeingDeleted
= TRUE
;
619 // it may also be GtkScrolledWindow in the case of an MDI child
620 if (GTK_IS_WINDOW(m_widget
))
622 gtk_window_set_focus( GTK_WINDOW(m_widget
), NULL
);
625 if (g_activeFrame
== this)
626 g_activeFrame
= NULL
;
627 if (g_lastActiveFrame
== this)
628 g_lastActiveFrame
= NULL
;
633 bool wxTopLevelWindowGTK::ShowFullScreen(bool show
, long style
)
635 if (show
== m_fsIsShowing
)
636 return FALSE
; // return what?
638 m_fsIsShowing
= show
;
640 wxX11FullScreenMethod method
=
641 wxGetFullScreenMethodX11((WXDisplay
*)GDK_DISPLAY(),
642 (WXWindow
)GDK_ROOT_WINDOW());
644 #if GTK_CHECK_VERSION(2,2,0)
645 // NB: gtk_window_fullscreen() uses freedesktop.org's WMspec extensions
646 // to switch to fullscreen, which is not always available. We must
647 // check if WM supports the spec and use legacy methods if it
649 if (method
== wxX11_FS_WMSPEC
)
652 gtk_window_fullscreen( GTK_WINDOW( m_widget
) );
654 gtk_window_unfullscreen( GTK_WINDOW( m_widget
) );
659 #endif // GTK+ >= 2.2.0
661 GdkWindow
*window
= m_widget
->window
;
665 m_fsSaveFlag
= style
;
666 GetPosition( &m_fsSaveFrame
.x
, &m_fsSaveFrame
.y
);
667 GetSize( &m_fsSaveFrame
.width
, &m_fsSaveFrame
.height
);
669 int screen_width
,screen_height
;
670 wxDisplaySize( &screen_width
, &screen_height
);
672 gint client_x
, client_y
, root_x
, root_y
;
675 if (method
!= wxX11_FS_WMSPEC
)
677 // don't do it always, Metacity hates it
678 m_fsSaveGdkFunc
= m_gdkFunc
;
679 m_fsSaveGdkDecor
= m_gdkDecor
;
680 m_gdkFunc
= m_gdkDecor
= 0;
681 gdk_window_set_decorations(window
, (GdkWMDecoration
)0);
682 gdk_window_set_functions(window
, (GdkWMFunction
)0);
685 gdk_window_get_origin (m_widget
->window
, &root_x
, &root_y
);
686 gdk_window_get_geometry (m_widget
->window
, &client_x
, &client_y
,
687 &width
, &height
, NULL
);
689 gdk_window_move_resize (m_widget
->window
, -client_x
, -client_y
,
690 screen_width
+ 1, screen_height
+ 1);
692 wxSetFullScreenStateX11((WXDisplay
*)GDK_DISPLAY(),
693 (WXWindow
)GDK_ROOT_WINDOW(),
694 (WXWindow
)GDK_WINDOW_XWINDOW(window
),
695 show
, &m_fsSaveFrame
, method
);
699 if (method
!= wxX11_FS_WMSPEC
)
701 // don't do it always, Metacity hates it
702 m_gdkFunc
= m_fsSaveGdkFunc
;
703 m_gdkDecor
= m_fsSaveGdkDecor
;
704 gdk_window_set_decorations(window
, (GdkWMDecoration
)m_gdkDecor
);
705 gdk_window_set_functions(window
, (GdkWMFunction
)m_gdkFunc
);
708 wxSetFullScreenStateX11((WXDisplay
*)GDK_DISPLAY(),
709 (WXWindow
)GDK_ROOT_WINDOW(),
710 (WXWindow
)GDK_WINDOW_XWINDOW(window
),
711 show
, &m_fsSaveFrame
, method
);
713 SetSize(m_fsSaveFrame
.x
, m_fsSaveFrame
.y
,
714 m_fsSaveFrame
.width
, m_fsSaveFrame
.height
);
721 // ----------------------------------------------------------------------------
722 // overridden wxWindow methods
723 // ----------------------------------------------------------------------------
725 bool wxTopLevelWindowGTK::Show( bool show
)
727 wxASSERT_MSG( (m_widget
!= NULL
), wxT("invalid frame") );
729 if (show
&& !m_sizeSet
)
731 /* by calling GtkOnSize here, we don't have to call
732 either after showing the frame, which would entail
733 much ugly flicker or from within the size_allocate
734 handler, because GTK 1.1.X forbids that. */
736 GtkOnSize( m_x
, m_y
, m_width
, m_height
);
740 gtk_widget_set_uposition( m_widget
, m_x
, m_y
);
742 return wxWindow::Show( show
);
745 void wxTopLevelWindowGTK::Raise()
748 gtk_window_present( GTK_WINDOW( m_widget
) );
754 void wxTopLevelWindowGTK::DoMoveWindow(int WXUNUSED(x
), int WXUNUSED(y
), int WXUNUSED(width
), int WXUNUSED(height
) )
756 wxFAIL_MSG( wxT("DoMoveWindow called for wxTopLevelWindowGTK") );
759 void wxTopLevelWindowGTK::DoSetSize( int x
, int y
, int width
, int height
, int sizeFlags
)
761 wxASSERT_MSG( (m_widget
!= NULL
), wxT("invalid frame") );
763 // this shouldn't happen: wxFrame, wxMDIParentFrame and wxMDIChildFrame have m_wxwindow
764 wxASSERT_MSG( (m_wxwindow
!= NULL
), wxT("invalid frame") );
774 int old_width
= m_width
;
775 int old_height
= m_height
;
777 if ((sizeFlags
& wxSIZE_ALLOW_MINUS_ONE
) == 0)
779 if (x
!= -1) m_x
= x
;
780 if (y
!= -1) m_y
= y
;
787 if (width
!= -1) m_width
= width
;
788 if (height
!= -1) m_height
= height
;
791 if ((sizeFlags & wxSIZE_AUTO_WIDTH) == wxSIZE_AUTO_WIDTH)
793 if (width == -1) m_width = 80;
796 if ((sizeFlags & wxSIZE_AUTO_HEIGHT) == wxSIZE_AUTO_HEIGHT)
798 if (height == -1) m_height = 26;
802 int minWidth
= GetMinWidth(),
803 minHeight
= GetMinHeight(),
804 maxWidth
= GetMaxWidth(),
805 maxHeight
= GetMaxHeight();
808 // GPE's window manager doesn't like size hints
809 // at all, esp. when the user has to use the
817 if ((minWidth
!= -1) && (m_width
< minWidth
)) m_width
= minWidth
;
818 if ((minHeight
!= -1) && (m_height
< minHeight
)) m_height
= minHeight
;
819 if ((maxWidth
!= -1) && (m_width
> maxWidth
)) m_width
= maxWidth
;
820 if ((maxHeight
!= -1) && (m_height
> maxHeight
)) m_height
= maxHeight
;
822 if ((m_x
!= -1) || (m_y
!= -1))
824 if ((m_x
!= old_x
) || (m_y
!= old_y
))
826 gtk_widget_set_uposition( m_widget
, m_x
, m_y
);
830 if ((m_width
!= old_width
) || (m_height
!= old_height
))
832 if (m_widget
->window
)
833 gdk_window_resize( m_widget
->window
, m_width
, m_height
);
835 gtk_window_set_default_size( GTK_WINDOW(m_widget
), m_width
, m_height
);
837 /* we set the size in GtkOnSize, i.e. mostly the actual resizing is
838 done either directly before the frame is shown or in idle time
839 so that different calls to SetSize() don't lead to flicker. */
846 void wxTopLevelWindowGTK::DoGetClientSize( int *width
, int *height
) const
848 wxASSERT_MSG( (m_widget
!= NULL
), wxT("invalid frame") );
850 wxWindow::DoGetClientSize( width
, height
);
854 *height
-= m_miniEdge
*2 + m_miniTitle
;
858 *width
-= m_miniEdge
*2;
862 void wxTopLevelWindowGTK::DoSetClientSize( int width
, int height
)
864 wxASSERT_MSG( (m_widget
!= NULL
), wxT("invalid frame") );
867 width
+ m_miniEdge
*2, height
+ m_miniEdge
*2 + m_miniTitle
, 0);
870 void wxTopLevelWindowGTK::GtkOnSize( int WXUNUSED(x
), int WXUNUSED(y
),
871 int width
, int height
)
873 // due to a bug in gtk, x,y are always 0
878 if (m_resizing
) return;
881 if ( m_wxwindow
== NULL
) return;
886 /* wxMDIChildFrame derives from wxFrame but it _is_ a wxWindow as it uses
887 wxWindow::Create to create it's GTK equivalent. m_mainWidget is only
888 set in wxFrame::Create so it is used to check what kind of frame we
889 have here. if m_mainWidget is NULL it is a wxMDIChildFrame and so we
890 skip the part which handles m_frameMenuBar, m_frameToolBar and (most
891 importantly) m_mainWidget */
893 int minWidth
= GetMinWidth(),
894 minHeight
= GetMinHeight(),
895 maxWidth
= GetMaxWidth(),
896 maxHeight
= GetMaxHeight();
899 // GPE's window manager doesn't like size hints
900 // at all, esp. when the user has to use the
908 if ((minWidth
!= -1) && (m_width
< minWidth
)) m_width
= minWidth
;
909 if ((minHeight
!= -1) && (m_height
< minHeight
)) m_height
= minHeight
;
910 if ((maxWidth
!= -1) && (m_width
> maxWidth
)) m_width
= maxWidth
;
911 if ((maxHeight
!= -1) && (m_height
> maxHeight
)) m_height
= maxHeight
;
916 gint flag
= 0; // GDK_HINT_POS;
919 if ((minWidth
!= -1) || (minHeight
!= -1)) flag
|= GDK_HINT_MIN_SIZE
;
920 if ((maxWidth
!= -1) || (maxHeight
!= -1)) flag
|= GDK_HINT_MAX_SIZE
;
922 geom
.min_width
= minWidth
;
923 geom
.min_height
= minHeight
;
925 // Because of the way we set GDK_HINT_MAX_SIZE above, if either of
926 // maxHeight or maxWidth is set, we must set them both, else the
927 // remaining -1 will be taken literally.
929 // I'm certain this also happens elsewhere, and is the probable
930 // cause of other such things as:
931 // Gtk-WARNING **: gtk_widget_size_allocate():
932 // attempt to allocate widget with width 65535 and height 600
933 // but I don't have time to track them all now..
935 // Really we need to encapulate all this height/width business and
936 // stop any old method from ripping at the members directly and
937 // scattering -1's without regard for who might resolve them later.
939 geom
.max_width
= ( maxHeight
== -1 ) ? maxWidth
940 : ( maxWidth
== -1 ) ? wxGetDisplaySize().GetWidth()
943 geom
.max_height
= ( maxWidth
== -1 ) ? maxHeight
// ( == -1 here )
944 : ( maxHeight
== -1 ) ? wxGetDisplaySize().GetHeight()
947 gtk_window_set_geometry_hints( GTK_WINDOW(m_widget
),
950 (GdkWindowHints
) flag
);
952 /* I revert back to wxGTK's original behaviour. m_mainWidget holds the
953 * menubar, the toolbar and the client area, which is represented by
955 * this hurts in the eye, but I don't want to call SetSize()
956 * because I don't want to call any non-native functions here. */
958 int client_x
= m_miniEdge
;
959 int client_y
= m_miniEdge
+ m_miniTitle
;
960 int client_w
= m_width
- 2*m_miniEdge
;
961 int client_h
= m_height
- 2*m_miniEdge
- m_miniTitle
;
963 gtk_pizza_set_size( GTK_PIZZA(m_mainWidget
),
965 client_x
, client_y
, client_w
, client_h
);
969 // If there is no m_mainWidget between m_widget and m_wxwindow there
970 // is no need to set the size or position of m_wxwindow.
975 // send size event to frame
976 wxSizeEvent
event( wxSize(m_width
,m_height
), GetId() );
977 event
.SetEventObject( this );
978 GetEventHandler()->ProcessEvent( event
);
983 void wxTopLevelWindowGTK::OnInternalIdle()
985 if (!m_sizeSet
&& GTK_WIDGET_REALIZED(m_wxwindow
))
987 GtkOnSize( m_x
, m_y
, m_width
, m_height
);
989 // we'll come back later
991 wxapp_install_idle_handler();
995 // set the focus if not done yet and if we can already do it
996 if ( GTK_WIDGET_REALIZED(m_wxwindow
) )
998 if ( g_delayedFocus
&&
999 wxGetTopLevelParent((wxWindow
*)g_delayedFocus
) == this )
1001 wxLogTrace(_T("focus"),
1002 _T("Setting focus from wxTLW::OnIdle() to %s(%s)"),
1003 g_delayedFocus
->GetClassInfo()->GetClassName(),
1004 g_delayedFocus
->GetLabel().c_str());
1006 g_delayedFocus
->SetFocus();
1007 g_delayedFocus
= NULL
;
1011 wxWindow::OnInternalIdle();
1013 // Synthetize activate events.
1014 if ( g_sendActivateEvent
!= -1 )
1016 bool activate
= g_sendActivateEvent
!= 0;
1018 // if (!activate) wxPrintf( wxT("de") );
1019 // wxPrintf( wxT("activate\n") );
1022 g_sendActivateEvent
= -1;
1024 wxTheApp
->SetActive(activate
, (wxWindow
*)g_lastActiveFrame
);
1028 // ----------------------------------------------------------------------------
1030 // ----------------------------------------------------------------------------
1032 void wxTopLevelWindowGTK::SetTitle( const wxString
&title
)
1034 wxASSERT_MSG( (m_widget
!= NULL
), wxT("invalid frame") );
1037 gtk_window_set_title( GTK_WINDOW(m_widget
), wxGTK_CONV( title
) );
1040 void wxTopLevelWindowGTK::SetIcon( const wxIcon
&icon
)
1042 SetIcons( wxIconBundle( icon
) );
1045 void wxTopLevelWindowGTK::SetIcons( const wxIconBundle
&icons
)
1047 wxASSERT_MSG( (m_widget
!= NULL
), wxT("invalid frame") );
1049 wxTopLevelWindowBase::SetIcons( icons
);
1053 size_t max
= icons
.m_icons
.GetCount();
1055 for (size_t i
= 0; i
< max
; i
++)
1057 if (icons
.m_icons
[i
].Ok())
1059 list
= g_list_prepend(list
, icons
.m_icons
[i
].GetPixbuf());
1062 gtk_window_set_icon_list(GTK_WINDOW(m_widget
), list
);
1065 #else // !__WXGTK20__
1066 GdkWindow
* window
= m_widget
->window
;
1070 wxIcon icon
= icons
.GetIcon(-1);
1073 wxMask
*mask
= icon
.GetMask();
1074 GdkBitmap
*bm
= (GdkBitmap
*) NULL
;
1075 if (mask
) bm
= mask
->GetBitmap();
1077 gdk_window_set_icon( m_widget
->window
, (GdkWindow
*) NULL
, icon
.GetPixmap(), bm
);
1080 wxSetIconsX11( (WXDisplay
*)GDK_WINDOW_XDISPLAY( window
),
1081 (WXWindow
)GDK_WINDOW_XWINDOW( window
), icons
);
1082 #endif // !__WXGTK20__
1085 // ----------------------------------------------------------------------------
1086 // frame state: maximized/iconized/normal
1087 // ----------------------------------------------------------------------------
1089 void wxTopLevelWindowGTK::Maximize(bool maximize
)
1093 gtk_window_maximize( GTK_WINDOW( m_widget
) );
1095 gtk_window_unmaximize( GTK_WINDOW( m_widget
) );
1097 wxFAIL_MSG( _T("not implemented") );
1101 bool wxTopLevelWindowGTK::IsMaximized() const
1104 if(!m_widget
->window
)
1107 return gdk_window_get_state(m_widget
->window
) & GDK_WINDOW_STATE_MAXIMIZED
;
1109 // wxFAIL_MSG( _T("not implemented") );
1111 // This is an approximation
1116 void wxTopLevelWindowGTK::Restore()
1119 // "Present" seems similar enough to "restore"
1120 gtk_window_present( GTK_WINDOW( m_widget
) );
1122 wxFAIL_MSG( _T("not implemented") );
1126 void wxTopLevelWindowGTK::Iconize( bool iconize
)
1130 gtk_window_iconify( GTK_WINDOW( m_widget
) );
1132 gtk_window_deiconify( GTK_WINDOW( m_widget
) );
1136 GdkWindow
*window
= m_widget
->window
;
1138 // you should do it later, for example from OnCreate() handler
1139 wxCHECK_RET( window
, _T("frame not created yet - can't iconize") );
1141 XIconifyWindow( GDK_WINDOW_XDISPLAY( window
),
1142 GDK_WINDOW_XWINDOW( window
),
1143 DefaultScreen( GDK_DISPLAY() ) );
1148 bool wxTopLevelWindowGTK::IsIconized() const
1150 return m_isIconized
;
1153 void wxTopLevelWindowGTK::SetIconizeState(bool iconize
)
1155 if ( iconize
!= m_isIconized
)
1157 m_isIconized
= iconize
;
1158 (void)SendIconizeEvent(iconize
);
1162 void wxTopLevelWindowGTK::AddGrab()
1167 gtk_grab_add( m_widget
);
1169 gtk_grab_remove( m_widget
);
1173 void wxTopLevelWindowGTK::RemoveGrab()
1184 static bool do_shape_combine_region(GdkWindow
* window
, const wxRegion
& region
)
1188 if (region
.IsEmpty())
1190 gdk_window_shape_combine_mask(window
, NULL
, 0, 0);
1195 gdk_window_shape_combine_region(window
, region
.GetRegion(), 0, 0);
1197 wxBitmap bmp
= region
.ConvertToBitmap();
1198 bmp
.SetMask(new wxMask(bmp
, *wxBLACK
));
1199 GdkBitmap
* mask
= bmp
.GetMask()->GetBitmap();
1200 gdk_window_shape_combine_mask(window
, mask
, 0, 0);
1209 bool wxTopLevelWindowGTK::SetShape(const wxRegion
& region
)
1211 wxCHECK_MSG( HasFlag(wxFRAME_SHAPED
), FALSE
,
1212 _T("Shaped windows must be created with the wxFRAME_SHAPED style."));
1214 GdkWindow
*window
= NULL
;
1217 window
= GTK_PIZZA(m_wxwindow
)->bin_window
;
1218 do_shape_combine_region(window
, region
);
1220 window
= m_widget
->window
;
1221 return do_shape_combine_region(window
, region
);
1224 bool wxTopLevelWindowGTK::IsActive()
1226 return (this == (wxTopLevelWindowGTK
*)g_activeFrame
);