1 /////////////////////////////////////////////////////////////////////////////
4 // Author: Robert Roebling
6 // Copyright: (c) 1998 Robert Roebling
7 // Licence: wxWindows licence
8 /////////////////////////////////////////////////////////////////////////////
10 // ============================================================================
12 // ============================================================================
14 // ----------------------------------------------------------------------------
16 // ----------------------------------------------------------------------------
18 #if defined(__GNUG__) && !defined(NO_GCC_PRAGMA)
19 #pragma implementation "toplevel.h"
22 // For compilers that support precompilation, includes "wx.h".
23 #include "wx/wxprec.h"
26 #define XIconifyWindow XICONIFYWINDOW
32 #include "wx/dialog.h"
33 #include "wx/control.h"
35 #include "wx/dcclient.h"
36 #include "wx/gtk/private.h"
38 #include "wx/settings.h"
43 #include <gdk/gdkkeysyms.h>
46 #include "wx/gtk/win_gtk.h"
48 #include "wx/unix/utilsx11.h"
51 #include <X11/Xatom.h>
53 // ----------------------------------------------------------------------------
55 // ----------------------------------------------------------------------------
57 extern void wxapp_install_idle_handler();
60 // ----------------------------------------------------------------------------
62 // ----------------------------------------------------------------------------
64 extern wxList wxPendingDelete
;
66 extern int g_openDialogs
;
67 extern wxWindowGTK
*g_delayedFocus
;
69 //-----------------------------------------------------------------------------
70 // "focus" from m_window
71 //-----------------------------------------------------------------------------
73 static gint
gtk_frame_focus_callback( GtkWidget
*widget
, GtkDirectionType
WXUNUSED(d
), wxWindow
*WXUNUSED(win
) )
76 wxapp_install_idle_handler();
78 // This disables GTK's tab traversal
79 gtk_signal_emit_stop_by_name( GTK_OBJECT(widget
), "focus" );
83 //-----------------------------------------------------------------------------
85 //-----------------------------------------------------------------------------
87 static void gtk_frame_size_callback( GtkWidget
*WXUNUSED(widget
), GtkAllocation
* alloc
, wxTopLevelWindowGTK
*win
)
90 wxapp_install_idle_handler();
95 if ((win
->m_width
!= alloc
->width
) || (win
->m_height
!= alloc
->height
))
98 wxPrintf( "OnSize from " );
99 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
100 wxPrintf( win->GetClassInfo()->GetClassName() );
101 wxPrintf( " %d %d %d %d\n", (int)alloc->x,
104 (int)alloc->height );
107 win
->m_width
= alloc
->width
;
108 win
->m_height
= alloc
->height
;
109 win
->m_queuedFullRedraw
= TRUE
;
110 win
->GtkUpdateSize();
114 //-----------------------------------------------------------------------------
116 //-----------------------------------------------------------------------------
118 static gint
gtk_frame_delete_callback( GtkWidget
*WXUNUSED(widget
), GdkEvent
*WXUNUSED(event
), wxTopLevelWindowGTK
*win
)
121 wxapp_install_idle_handler();
123 if (win
->IsEnabled() &&
124 (g_openDialogs
== 0 || (win
->GetExtraStyle() & wxTOPLEVEL_EX_DIALOG
) ||
132 //-----------------------------------------------------------------------------
134 //-----------------------------------------------------------------------------
137 gtk_frame_configure_callback( GtkWidget
*WXUNUSED(widget
), GdkEventConfigure
*WXUNUSED(event
), wxTopLevelWindowGTK
*win
)
140 wxapp_install_idle_handler();
142 if (!win
->m_hasVMT
|| !win
->IsShown())
147 gdk_window_get_root_origin( win
->m_widget
->window
, &x
, &y
);
151 wxMoveEvent
mevent( wxPoint(win
->m_x
,win
->m_y
), win
->GetId() );
152 mevent
.SetEventObject( win
);
153 win
->GetEventHandler()->ProcessEvent( mevent
);
158 //-----------------------------------------------------------------------------
159 // "realize" from m_widget
160 //-----------------------------------------------------------------------------
162 // we cannot MWM hints and icons before the widget has been realized,
163 // so we do this directly after realization
166 gtk_frame_realized_callback( GtkWidget
* WXUNUSED(widget
),
167 wxTopLevelWindowGTK
*win
)
170 wxapp_install_idle_handler();
172 // All this is for Motif Window Manager "hints" and is supposed to be
173 // recognized by other WM as well. Not tested.
174 gdk_window_set_decorations(win
->m_widget
->window
,
175 (GdkWMDecoration
)win
->m_gdkDecor
);
176 gdk_window_set_functions(win
->m_widget
->window
,
177 (GdkWMFunction
)win
->m_gdkFunc
);
179 // GTK's shrinking/growing policy
180 if ((win
->m_gdkFunc
& GDK_FUNC_RESIZE
) == 0)
181 gtk_window_set_policy(GTK_WINDOW(win
->m_widget
), 0, 0, 1);
183 gtk_window_set_policy(GTK_WINDOW(win
->m_widget
), 1, 1, 1);
186 wxIconBundle iconsOld
= win
->GetIcons();
187 if ( iconsOld
.GetIcon(-1).Ok() )
189 win
->SetIcon( wxNullIcon
);
190 win
->SetIcons( iconsOld
);
194 //-----------------------------------------------------------------------------
195 // "map_event" from m_widget
196 //-----------------------------------------------------------------------------
199 gtk_frame_map_callback( GtkWidget
* WXUNUSED(widget
),
200 GdkEvent
* WXUNUSED(event
),
201 wxTopLevelWindow
*win
)
203 win
->SetIconizeState(FALSE
);
206 //-----------------------------------------------------------------------------
207 // "unmap_event" from m_widget
208 //-----------------------------------------------------------------------------
211 gtk_frame_unmap_callback( GtkWidget
* WXUNUSED(widget
),
212 GdkEvent
* WXUNUSED(event
),
213 wxTopLevelWindow
*win
)
215 win
->SetIconizeState(TRUE
);
218 //-----------------------------------------------------------------------------
219 // "expose_event" of m_client
220 //-----------------------------------------------------------------------------
222 static int gtk_window_expose_callback( GtkWidget
*widget
, GdkEventExpose
*gdk_event
, wxWindow
*win
)
224 GtkPizza
*pizza
= GTK_PIZZA(widget
);
226 gtk_paint_flat_box (win
->m_widget
->style
,
227 pizza
->bin_window
, GTK_STATE_NORMAL
,
237 //-----------------------------------------------------------------------------
238 // "draw" of m_client
239 //-----------------------------------------------------------------------------
243 static void gtk_window_draw_callback( GtkWidget
*widget
, GdkRectangle
*rect
, wxWindow
*win
)
245 GtkPizza
*pizza
= GTK_PIZZA(widget
);
247 gtk_paint_flat_box (win
->m_widget
->style
,
248 pizza
->bin_window
, GTK_STATE_NORMAL
,
258 // ----------------------------------------------------------------------------
259 // wxTopLevelWindowGTK itself
260 // ----------------------------------------------------------------------------
262 //-----------------------------------------------------------------------------
263 // InsertChild for wxTopLevelWindowGTK
264 //-----------------------------------------------------------------------------
266 /* Callback for wxTopLevelWindowGTK. This very strange beast has to be used because
267 * C++ has no virtual methods in a constructor. We have to emulate a
268 * virtual function here as wxWidgets requires different ways to insert
269 * a child in container classes. */
271 static void wxInsertChildInTopLevelWindow( wxTopLevelWindowGTK
* parent
, wxWindow
* child
)
273 wxASSERT( GTK_IS_WIDGET(child
->m_widget
) );
275 if (!parent
->m_insertInClientArea
)
277 // these are outside the client area
278 wxTopLevelWindowGTK
* frame
= (wxTopLevelWindowGTK
*) parent
;
279 gtk_pizza_put( GTK_PIZZA(frame
->m_mainWidget
),
280 GTK_WIDGET(child
->m_widget
),
288 // these are inside the client area
289 gtk_pizza_put( GTK_PIZZA(parent
->m_wxwindow
),
290 GTK_WIDGET(child
->m_widget
),
297 // resize on OnInternalIdle
298 parent
->GtkUpdateSize();
301 // ----------------------------------------------------------------------------
302 // wxTopLevelWindowGTK creation
303 // ----------------------------------------------------------------------------
305 void wxTopLevelWindowGTK
::Init()
310 m_mainWidget
= (GtkWidget
*) NULL
;
311 m_insertInClientArea
= TRUE
;
312 m_isIconized
= FALSE
;
313 m_fsIsShowing
= FALSE
;
314 m_themeEnabled
= TRUE
;
315 m_gdkDecor
= m_gdkFunc
= 0;
319 bool wxTopLevelWindowGTK
::Create( wxWindow
*parent
,
321 const wxString
& title
,
323 const wxSize
& sizeOrig
,
325 const wxString
&name
)
327 // always create a frame of some reasonable, even if arbitrary, size (at
328 // least for MSW compatibility)
329 wxSize size
= sizeOrig
;
330 size
.x
= WidthDefault(size
.x
);
331 size
.y
= HeightDefault(size
.y
);
333 wxTopLevelWindows
.Append( this );
335 m_needParent
= FALSE
;
337 if (!PreCreation( parent
, pos
, size
) ||
338 !CreateBase( parent
, id
, pos
, size
, style
, wxDefaultValidator
, name
))
340 wxFAIL_MSG( wxT("wxTopLevelWindowGTK creation failed") );
346 m_insertCallback
= (wxInsertChildFunction
) wxInsertChildInTopLevelWindow
;
348 // NB: m_widget may be !=NULL if it was created by derived class' Create,
349 // e.g. in wxTaskBarIconAreaGTK
350 if (m_widget
== NULL
)
352 GtkWindowType win_type
= GTK_WINDOW_TOPLEVEL
;
353 if (style
& wxFRAME_TOOL_WINDOW
)
354 win_type
= GTK_WINDOW_POPUP
;
356 if (GetExtraStyle() & wxTOPLEVEL_EX_DIALOG
)
359 m_widget
= gtk_window_new(GTK_WINDOW_TOPLEVEL
);
360 // Tell WM that this is a dialog window and make it center
361 // on parent by default (this is what GtkDialog ctor does):
362 gtk_window_set_type_hint(GTK_WINDOW(m_widget
),
363 GDK_WINDOW_TYPE_HINT_DIALOG
);
364 gtk_window_set_position(GTK_WINDOW(m_widget
),
365 GTK_WIN_POS_CENTER_ON_PARENT
);
367 m_widget
= gtk_window_new(GTK_WINDOW_DIALOG
);
372 m_widget
= gtk_window_new(win_type
);
376 if (m_parent
&& (((GTK_IS_WINDOW(m_parent
->m_widget
)) &&
377 (GetExtraStyle() & wxTOPLEVEL_EX_DIALOG
)) ||
378 (style
& wxFRAME_FLOAT_ON_PARENT
)))
380 gtk_window_set_transient_for( GTK_WINDOW(m_widget
), GTK_WINDOW(m_parent
->m_widget
) );
384 gtk_window_set_wmclass( GTK_WINDOW(m_widget
), wxGTK_CONV( name
), wxGTK_CONV( name
) );
386 gtk_window_set_title( GTK_WINDOW(m_widget
), wxGTK_CONV( title
) );
387 GTK_WIDGET_UNSET_FLAGS( m_widget
, GTK_CAN_FOCUS
);
389 gtk_signal_connect( GTK_OBJECT(m_widget
), "delete_event",
390 GTK_SIGNAL_FUNC(gtk_frame_delete_callback
), (gpointer
)this );
392 // m_mainWidget holds the toolbar, the menubar and the client area
393 m_mainWidget
= gtk_pizza_new();
394 gtk_widget_show( m_mainWidget
);
395 GTK_WIDGET_UNSET_FLAGS( m_mainWidget
, GTK_CAN_FOCUS
);
396 gtk_container_add( GTK_CONTAINER(m_widget
), m_mainWidget
);
398 if (m_miniEdge
== 0) // wxMiniFrame has its own version.
400 // For m_mainWidget themes
401 gtk_signal_connect( GTK_OBJECT(m_mainWidget
), "expose_event",
402 GTK_SIGNAL_FUNC(gtk_window_expose_callback
), (gpointer
)this );
404 gtk_signal_connect( GTK_OBJECT(m_mainWidget
), "draw",
405 GTK_SIGNAL_FUNC(gtk_window_draw_callback
), (gpointer
)this );
409 // m_wxwindow only represents the client area without toolbar and menubar
410 m_wxwindow
= gtk_pizza_new();
411 gtk_widget_show( m_wxwindow
);
412 gtk_container_add( GTK_CONTAINER(m_mainWidget
), m_wxwindow
);
414 // we donm't allow the frame to get the focus as otherwise
415 // the frame will grab it at arbitrary focus changes
416 GTK_WIDGET_UNSET_FLAGS( m_wxwindow
, GTK_CAN_FOCUS
);
418 if (m_parent
) m_parent
->AddChild( this );
420 // the user resized the frame by dragging etc.
421 gtk_signal_connect( GTK_OBJECT(m_widget
), "size_allocate",
422 GTK_SIGNAL_FUNC(gtk_frame_size_callback
), (gpointer
)this );
426 if ((m_x
!= -1) || (m_y
!= -1))
427 gtk_widget_set_uposition( m_widget
, m_x
, m_y
);
429 gtk_window_set_default_size( GTK_WINDOW(m_widget
), m_width
, m_height
);
431 // we cannot set MWM hints and icons before the widget has
432 // been realized, so we do this directly after realization
433 gtk_signal_connect( GTK_OBJECT(m_widget
), "realize",
434 GTK_SIGNAL_FUNC(gtk_frame_realized_callback
), (gpointer
) this );
436 // the only way to get the window size is to connect to this event
437 gtk_signal_connect( GTK_OBJECT(m_widget
), "configure_event",
438 GTK_SIGNAL_FUNC(gtk_frame_configure_callback
), (gpointer
)this );
440 // map and unmap for iconized state
441 gtk_signal_connect( GTK_OBJECT(m_widget
), "map_event",
442 GTK_SIGNAL_FUNC(gtk_frame_map_callback
), (gpointer
)this );
443 gtk_signal_connect( GTK_OBJECT(m_widget
), "unmap_event",
444 GTK_SIGNAL_FUNC(gtk_frame_unmap_callback
), (gpointer
)this );
446 // the only way to get the window size is to connect to this event
447 gtk_signal_connect( GTK_OBJECT(m_widget
), "configure_event",
448 GTK_SIGNAL_FUNC(gtk_frame_configure_callback
), (gpointer
)this );
450 // disable native tab traversal
451 gtk_signal_connect( GTK_OBJECT(m_widget
), "focus",
452 GTK_SIGNAL_FUNC(gtk_frame_focus_callback
), (gpointer
)this );
455 if ((m_miniEdge
> 0) || (style
& wxSIMPLE_BORDER
) || (style
& wxNO_BORDER
))
462 m_gdkDecor
= (long) GDK_DECOR_BORDER
;
463 m_gdkFunc
= (long) GDK_FUNC_MOVE
;
465 // All this is for Motif Window Manager "hints" and is supposed to be
466 // recognized by other WMs as well.
467 if ((style
& wxCAPTION
) != 0)
469 m_gdkDecor
|= GDK_DECOR_TITLE
;
471 if ((style
& wxCLOSE_BOX
) != 0)
473 m_gdkFunc
|= GDK_FUNC_CLOSE
;
475 if ((style
& wxSYSTEM_MENU
) != 0)
477 m_gdkDecor
|= GDK_DECOR_MENU
;
479 if ((style
& wxMINIMIZE_BOX
) != 0)
481 m_gdkFunc
|= GDK_FUNC_MINIMIZE
;
482 m_gdkDecor
|= GDK_DECOR_MINIMIZE
;
484 if ((style
& wxMAXIMIZE_BOX
) != 0)
486 m_gdkFunc
|= GDK_FUNC_MAXIMIZE
;
487 m_gdkDecor
|= GDK_DECOR_MAXIMIZE
;
489 if ((style
& wxRESIZE_BORDER
) != 0)
491 m_gdkFunc
|= GDK_FUNC_RESIZE
;
492 m_gdkDecor
|= GDK_DECOR_RESIZEH
;
499 wxTopLevelWindowGTK
::~wxTopLevelWindowGTK()
503 wxASSERT_MSG( FALSE
, _T("Window still grabbed"));
507 m_isBeingDeleted
= TRUE
;
509 // it may also be GtkScrolledWindow in the case of an MDI child
510 if (GTK_IS_WINDOW(m_widget
))
512 gtk_window_set_focus( GTK_WINDOW(m_widget
), NULL
);
518 bool wxTopLevelWindowGTK
::ShowFullScreen(bool show
, long style
)
520 if (show
== m_fsIsShowing
) return FALSE
; // return what?
522 m_fsIsShowing
= show
;
524 GdkWindow
*window
= m_widget
->window
;
525 wxX11FullScreenMethod method
=
526 wxGetFullScreenMethodX11((WXDisplay
*)GDK_DISPLAY(),
527 (WXWindow
)GDK_ROOT_WINDOW());
531 m_fsSaveFlag
= style
;
532 GetPosition( &m_fsSaveFrame
.x
, &m_fsSaveFrame
.y
);
533 GetSize( &m_fsSaveFrame
.width
, &m_fsSaveFrame
.height
);
535 int screen_width
,screen_height
;
536 wxDisplaySize( &screen_width
, &screen_height
);
538 gint client_x
, client_y
, root_x
, root_y
;
541 if (method
!= wxX11_FS_WMSPEC
)
543 // don't do it always, Metacity hates it
544 m_fsSaveGdkFunc
= m_gdkFunc
;
545 m_fsSaveGdkDecor
= m_gdkDecor
;
546 m_gdkFunc
= m_gdkDecor
= 0;
547 gdk_window_set_decorations(window
, (GdkWMDecoration
)0);
548 gdk_window_set_functions(window
, (GdkWMFunction
)0);
551 gdk_window_get_origin (m_widget
->window
, &root_x
, &root_y
);
552 gdk_window_get_geometry (m_widget
->window
, &client_x
, &client_y
,
553 &width
, &height
, NULL
);
555 gdk_window_move_resize (m_widget
->window
, -client_x
, -client_y
,
556 screen_width
+ 1, screen_height
+ 1);
558 wxSetFullScreenStateX11((WXDisplay
*)GDK_DISPLAY(),
559 (WXWindow
)GDK_ROOT_WINDOW(),
560 (WXWindow
)GDK_WINDOW_XWINDOW(window
),
561 show
, &m_fsSaveFrame
, method
);
565 if (method
!= wxX11_FS_WMSPEC
)
567 // don't do it always, Metacity hates it
568 m_gdkFunc
= m_fsSaveGdkFunc
;
569 m_gdkDecor
= m_fsSaveGdkDecor
;
570 gdk_window_set_decorations(window
, (GdkWMDecoration
)m_gdkDecor
);
571 gdk_window_set_functions(window
, (GdkWMFunction
)m_gdkFunc
);
574 wxSetFullScreenStateX11((WXDisplay
*)GDK_DISPLAY(),
575 (WXWindow
)GDK_ROOT_WINDOW(),
576 (WXWindow
)GDK_WINDOW_XWINDOW(window
),
577 show
, &m_fsSaveFrame
, method
);
579 SetSize(m_fsSaveFrame
.x
, m_fsSaveFrame
.y
,
580 m_fsSaveFrame
.width
, m_fsSaveFrame
.height
);
587 // ----------------------------------------------------------------------------
588 // overridden wxWindow methods
589 // ----------------------------------------------------------------------------
591 bool wxTopLevelWindowGTK
::Show( bool show
)
593 wxASSERT_MSG( (m_widget
!= NULL
), wxT("invalid frame") );
595 if (show
&& !m_sizeSet
)
597 /* by calling GtkOnSize here, we don't have to call
598 either after showing the frame, which would entail
599 much ugly flicker or from within the size_allocate
600 handler, because GTK 1.1.X forbids that. */
602 GtkOnSize( m_x
, m_y
, m_width
, m_height
);
605 return wxWindow
::Show( show
);
608 void wxTopLevelWindowGTK
::DoMoveWindow(int WXUNUSED(x
), int WXUNUSED(y
), int WXUNUSED(width
), int WXUNUSED(height
) )
610 wxFAIL_MSG( wxT("DoMoveWindow called for wxTopLevelWindowGTK") );
613 void wxTopLevelWindowGTK
::DoSetSize( int x
, int y
, int width
, int height
, int sizeFlags
)
615 wxASSERT_MSG( (m_widget
!= NULL
), wxT("invalid frame") );
617 // this shouldn't happen: wxFrame, wxMDIParentFrame and wxMDIChildFrame have m_wxwindow
618 wxASSERT_MSG( (m_wxwindow
!= NULL
), wxT("invalid frame") );
628 int old_width
= m_width
;
629 int old_height
= m_height
;
631 if ((sizeFlags
& wxSIZE_ALLOW_MINUS_ONE
) == 0)
633 if (x
!= -1) m_x
= x
;
634 if (y
!= -1) m_y
= y
;
641 if (width
!= -1) m_width
= width
;
642 if (height
!= -1) m_height
= height
;
645 if ((sizeFlags & wxSIZE_AUTO_WIDTH) == wxSIZE_AUTO_WIDTH)
647 if (width == -1) m_width = 80;
650 if ((sizeFlags & wxSIZE_AUTO_HEIGHT) == wxSIZE_AUTO_HEIGHT)
652 if (height == -1) m_height = 26;
656 int minWidth
= GetMinWidth(),
657 minHeight
= GetMinHeight(),
658 maxWidth
= GetMaxWidth(),
659 maxHeight
= GetMaxHeight();
662 // GPE's window manager doesn't like size hints
663 // at all, esp. when the user has to use the
671 if ((minWidth
!= -1) && (m_width
< minWidth
)) m_width
= minWidth
;
672 if ((minHeight
!= -1) && (m_height
< minHeight
)) m_height
= minHeight
;
673 if ((maxWidth
!= -1) && (m_width
> maxWidth
)) m_width
= maxWidth
;
674 if ((maxHeight
!= -1) && (m_height
> maxHeight
)) m_height
= maxHeight
;
676 if ((m_x
!= -1) || (m_y
!= -1))
678 if ((m_x
!= old_x
) || (m_y
!= old_y
))
680 gtk_widget_set_uposition( m_widget
, m_x
, m_y
);
684 if ((m_width
!= old_width
) || (m_height
!= old_height
))
686 if (m_widget
->window
)
687 gdk_window_resize( m_widget
->window
, m_width
, m_height
);
689 gtk_window_set_default_size( GTK_WINDOW(m_widget
), m_width
, m_height
);
691 /* we set the size in GtkOnSize, i.e. mostly the actual resizing is
692 done either directly before the frame is shown or in idle time
693 so that different calls to SetSize() don't lead to flicker. */
700 void wxTopLevelWindowGTK
::DoGetClientSize( int *width
, int *height
) const
702 wxASSERT_MSG( (m_widget
!= NULL
), wxT("invalid frame") );
704 wxWindow
::DoGetClientSize( width
, height
);
708 *height
-= m_miniEdge
*2 + m_miniTitle
;
712 *width
-= m_miniEdge
*2;
716 void wxTopLevelWindowGTK
::DoSetClientSize( int width
, int height
)
718 wxASSERT_MSG( (m_widget
!= NULL
), wxT("invalid frame") );
721 width
+ m_miniEdge
*2, height
+ m_miniEdge
*2 + m_miniTitle
, 0);
724 void wxTopLevelWindowGTK
::GtkOnSize( int WXUNUSED(x
), int WXUNUSED(y
),
725 int width
, int height
)
727 // due to a bug in gtk, x,y are always 0
732 if (m_resizing
) return;
735 if ( m_wxwindow
== NULL
) return;
740 /* wxMDIChildFrame derives from wxFrame but it _is_ a wxWindow as it uses
741 wxWindow::Create to create it's GTK equivalent. m_mainWidget is only
742 set in wxFrame::Create so it is used to check what kind of frame we
743 have here. if m_mainWidget is NULL it is a wxMDIChildFrame and so we
744 skip the part which handles m_frameMenuBar, m_frameToolBar and (most
745 importantly) m_mainWidget */
747 int minWidth
= GetMinWidth(),
748 minHeight
= GetMinHeight(),
749 maxWidth
= GetMaxWidth(),
750 maxHeight
= GetMaxHeight();
753 // GPE's window manager doesn't like size hints
754 // at all, esp. when the user has to use the
762 if ((minWidth
!= -1) && (m_width
< minWidth
)) m_width
= minWidth
;
763 if ((minHeight
!= -1) && (m_height
< minHeight
)) m_height
= minHeight
;
764 if ((maxWidth
!= -1) && (m_width
> maxWidth
)) m_width
= maxWidth
;
765 if ((maxHeight
!= -1) && (m_height
> maxHeight
)) m_height
= maxHeight
;
770 gint flag
= 0; // GDK_HINT_POS;
773 if ((minWidth
!= -1) || (minHeight
!= -1)) flag
|= GDK_HINT_MIN_SIZE
;
774 if ((maxWidth
!= -1) || (maxHeight
!= -1)) flag
|= GDK_HINT_MAX_SIZE
;
776 geom
.min_width
= minWidth
;
777 geom
.min_height
= minHeight
;
779 // Because of the way we set GDK_HINT_MAX_SIZE above, if either of
780 // maxHeight or maxWidth is set, we must set them both, else the
781 // remaining -1 will be taken literally.
783 // I'm certain this also happens elsewhere, and is the probable
784 // cause of other such things as:
785 // Gtk-WARNING **: gtk_widget_size_allocate():
786 // attempt to allocate widget with width 65535 and height 600
787 // but I don't have time to track them all now..
789 // Really we need to encapulate all this height/width business and
790 // stop any old method from ripping at the members directly and
791 // scattering -1's without regard for who might resolve them later.
793 geom
.max_width
= ( maxHeight
== -1 ) ? maxWidth
794 : ( maxWidth
== -1 ) ?
wxGetDisplaySize().GetWidth()
797 geom
.max_height
= ( maxWidth
== -1 ) ? maxHeight
// ( == -1 here )
798 : ( maxHeight
== -1 ) ?
wxGetDisplaySize().GetHeight()
801 gtk_window_set_geometry_hints( GTK_WINDOW(m_widget
),
804 (GdkWindowHints
) flag
);
806 /* I revert back to wxGTK's original behaviour. m_mainWidget holds the
807 * menubar, the toolbar and the client area, which is represented by
809 * this hurts in the eye, but I don't want to call SetSize()
810 * because I don't want to call any non-native functions here. */
812 int client_x
= m_miniEdge
;
813 int client_y
= m_miniEdge
+ m_miniTitle
;
814 int client_w
= m_width
- 2*m_miniEdge
;
815 int client_h
= m_height
- 2*m_miniEdge
- m_miniTitle
;
817 gtk_pizza_set_size( GTK_PIZZA(m_mainWidget
),
819 client_x
, client_y
, client_w
, client_h
);
823 // If there is no m_mainWidget between m_widget and m_wxwindow there
824 // is no need to set the size or position of m_wxwindow.
829 // send size event to frame
830 wxSizeEvent
event( wxSize(m_width
,m_height
), GetId() );
831 event
.SetEventObject( this );
832 GetEventHandler()->ProcessEvent( event
);
837 void wxTopLevelWindowGTK
::OnInternalIdle()
839 if (!m_sizeSet
&& GTK_WIDGET_REALIZED(m_wxwindow
))
841 GtkOnSize( m_x
, m_y
, m_width
, m_height
);
843 // we'll come back later
845 wxapp_install_idle_handler();
849 // set the focus if not done yet and if we can already do it
850 if ( GTK_WIDGET_REALIZED(m_wxwindow
) )
852 if ( g_delayedFocus
&&
853 wxGetTopLevelParent((wxWindow
*)g_delayedFocus
) == this )
855 wxLogTrace(_T("focus"),
856 _T("Setting focus from wxTLW::OnIdle() to %s(%s)"),
857 g_delayedFocus
->GetClassInfo()->GetClassName(),
858 g_delayedFocus
->GetLabel().c_str());
860 g_delayedFocus
->SetFocus();
861 g_delayedFocus
= NULL
;
865 wxWindow
::OnInternalIdle();
868 // ----------------------------------------------------------------------------
870 // ----------------------------------------------------------------------------
872 void wxTopLevelWindowGTK
::SetTitle( const wxString
&title
)
874 wxASSERT_MSG( (m_widget
!= NULL
), wxT("invalid frame") );
877 gtk_window_set_title( GTK_WINDOW(m_widget
), wxGTK_CONV( title
) );
880 void wxTopLevelWindowGTK
::DoSetIcon( const wxIcon
&icon
)
885 if (!m_widget
->window
)
888 wxMask
*mask
= icon
.GetMask();
889 GdkBitmap
*bm
= (GdkBitmap
*) NULL
;
890 if (mask
) bm
= mask
->GetBitmap();
892 gdk_window_set_icon( m_widget
->window
, (GdkWindow
*) NULL
, icon
.GetPixmap(), bm
);
895 void wxTopLevelWindowGTK
::SetIcon( const wxIcon
&icon
)
897 SetIcons( wxIconBundle( icon
) );
900 void wxTopLevelWindowGTK
::SetIcons( const wxIconBundle
&icons
)
902 wxASSERT_MSG( (m_widget
!= NULL
), wxT("invalid frame") );
903 GdkWindow
* window
= m_widget
->window
;
905 wxTopLevelWindowBase
::SetIcons( icons
);
907 DoSetIcon( icons
.GetIcon( -1 ) );
910 wxSetIconsX11( (WXDisplay
*)GDK_WINDOW_XDISPLAY( window
),
911 (WXWindow
)GDK_WINDOW_XWINDOW( window
), icons
);
915 // ----------------------------------------------------------------------------
916 // frame state: maximized/iconized/normal
917 // ----------------------------------------------------------------------------
919 void wxTopLevelWindowGTK
::Maximize(bool maximize
)
923 gtk_window_maximize( GTK_WINDOW( m_widget
) );
925 gtk_window_unmaximize( GTK_WINDOW( m_widget
) );
927 wxFAIL_MSG( _T("not implemented") );
931 bool wxTopLevelWindowGTK
::IsMaximized() const
933 // wxFAIL_MSG( _T("not implemented") );
935 // This is an approximation
939 void wxTopLevelWindowGTK
::Restore()
942 // "Present" seems similar enough to "restore"
943 gtk_window_present( GTK_WINDOW( m_widget
) );
945 wxFAIL_MSG( _T("not implemented") );
949 void wxTopLevelWindowGTK
::Iconize( bool iconize
)
953 gtk_window_iconify( GTK_WINDOW( m_widget
) );
955 gtk_window_deiconify( GTK_WINDOW( m_widget
) );
959 GdkWindow
*window
= m_widget
->window
;
961 // you should do it later, for example from OnCreate() handler
962 wxCHECK_RET( window
, _T("frame not created yet - can't iconize") );
964 XIconifyWindow( GDK_WINDOW_XDISPLAY( window
),
965 GDK_WINDOW_XWINDOW( window
),
966 DefaultScreen( GDK_DISPLAY() ) );
971 bool wxTopLevelWindowGTK
::IsIconized() const
976 void wxTopLevelWindowGTK
::SetIconizeState(bool iconize
)
978 if ( iconize
!= m_isIconized
)
980 m_isIconized
= iconize
;
981 (void)SendIconizeEvent(iconize
);
985 void wxTopLevelWindowGTK
::AddGrab()
990 gtk_grab_add( m_widget
);
992 gtk_grab_remove( m_widget
);
996 void wxTopLevelWindowGTK
::RemoveGrab()
1007 static bool do_shape_combine_region(GdkWindow
* window
, const wxRegion
& region
)
1011 if (region
.IsEmpty())
1013 gdk_window_shape_combine_mask(window
, NULL
, 0, 0);
1018 gdk_window_shape_combine_region(window
, region
.GetRegion(), 0, 0);
1020 wxBitmap bmp
= region
.ConvertToBitmap();
1021 bmp
.SetMask(new wxMask(bmp
, *wxBLACK
));
1022 GdkBitmap
* mask
= bmp
.GetMask()->GetBitmap();
1023 gdk_window_shape_combine_mask(window
, mask
, 0, 0);
1032 bool wxTopLevelWindowGTK
::SetShape(const wxRegion
& region
)
1034 wxCHECK_MSG( HasFlag(wxFRAME_SHAPED
), FALSE
,
1035 _T("Shaped windows must be created with the wxFRAME_SHAPED style."));
1037 GdkWindow
*window
= NULL
;
1040 window
= GTK_PIZZA(m_wxwindow
)->bin_window
;
1041 do_shape_combine_region(window
, region
);
1043 window
= m_widget
->window
;
1044 return do_shape_combine_region(window
, region
);