]> git.saurik.com Git - wxWidgets.git/blame - src/gtk/toplevel.cpp
select the whole text in the single line text control when its SetFocus() is called...
[wxWidgets.git] / src / gtk / toplevel.cpp
CommitLineData
7d9f12f3
VS
1/////////////////////////////////////////////////////////////////////////////
2// Name: toplevel.cpp
3// Purpose:
4// Author: Robert Roebling
5// Id: $Id$
6// Copyright: (c) 1998 Robert Roebling
7// Licence: wxWindows licence
8/////////////////////////////////////////////////////////////////////////////
9
10// ============================================================================
11// declarations
12// ============================================================================
13
14// ----------------------------------------------------------------------------
15// headers
16// ----------------------------------------------------------------------------
17
18#ifdef __GNUG__
19 #pragma implementation "toplevel.h"
20#endif
21
22#ifdef __VMS
23#define XIconifyWindow XICONIFYWINDOW
24#endif
25
26#include "wx/defs.h"
27
28#include "wx/dialog.h"
29#include "wx/control.h"
30#include "wx/app.h"
31#include "wx/dcclient.h"
32
33#include <glib.h>
34#include <gdk/gdk.h>
35#include <gtk/gtk.h>
36#include <gdk/gdkkeysyms.h>
37#include <gdk/gdkx.h>
38
39#include "wx/gtk/win_gtk.h"
40
f618020a
MB
41#include "wx/unix/utilsx11.h"
42
7d9f12f3
VS
43// ----------------------------------------------------------------------------
44// idle system
45// ----------------------------------------------------------------------------
46
47extern void wxapp_install_idle_handler();
48extern bool g_isIdle;
7d9f12f3 49
7d9f12f3
VS
50// ----------------------------------------------------------------------------
51// data
52// ----------------------------------------------------------------------------
53
d7fa7eaa
RR
54extern wxList wxPendingDelete;
55
56extern int g_openDialogs;
57extern wxWindowGTK *g_delayedFocus;
7d9f12f3
VS
58
59// ----------------------------------------------------------------------------
60// debug
61// ----------------------------------------------------------------------------
62
63#ifdef __WXDEBUG__
64
65extern void debug_focus_in( GtkWidget* widget, const wxChar* name, const wxChar *window );
66
67#endif
68
7d9f12f3
VS
69//-----------------------------------------------------------------------------
70// "focus" from m_window
71//-----------------------------------------------------------------------------
72
73static gint gtk_frame_focus_callback( GtkWidget *widget, GtkDirectionType WXUNUSED(d), wxWindow *WXUNUSED(win) )
74{
75 if (g_isIdle)
76 wxapp_install_idle_handler();
77
78 // This disables GTK's tab traversal
79 gtk_signal_emit_stop_by_name( GTK_OBJECT(widget), "focus" );
80 return TRUE;
81}
82
83//-----------------------------------------------------------------------------
84// "size_allocate"
85//-----------------------------------------------------------------------------
86
87static void gtk_frame_size_callback( GtkWidget *WXUNUSED(widget), GtkAllocation* alloc, wxTopLevelWindowGTK *win )
88{
89 if (g_isIdle)
90 wxapp_install_idle_handler();
91
92 if (!win->m_hasVMT)
93 return;
94
95 if ((win->m_width != alloc->width) || (win->m_height != alloc->height))
96 {
97/*
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,
102 (int)alloc->y,
103 (int)alloc->width,
104 (int)alloc->height );
105*/
106
107 win->m_width = alloc->width;
108 win->m_height = alloc->height;
109 win->m_queuedFullRedraw = TRUE;
110 win->GtkUpdateSize();
111 }
112}
113
114//-----------------------------------------------------------------------------
115// "delete_event"
116//-----------------------------------------------------------------------------
117
118static gint gtk_frame_delete_callback( GtkWidget *WXUNUSED(widget), GdkEvent *WXUNUSED(event), wxTopLevelWindowGTK *win )
119{
120 if (g_isIdle)
121 wxapp_install_idle_handler();
122
123 if (win->IsEnabled() &&
f819b4a3 124 (g_openDialogs == 0 || (win->GetExtraStyle() & wxTOPLEVEL_EX_DIALOG)))
7d9f12f3
VS
125 win->Close();
126
127 return TRUE;
128}
129
130
131//-----------------------------------------------------------------------------
132// "configure_event"
133//-----------------------------------------------------------------------------
134
135static gint
7d9f12f3 136gtk_frame_configure_callback( GtkWidget *WXUNUSED(widget), GdkEventConfigure *WXUNUSED(event), wxTopLevelWindowGTK *win )
7d9f12f3
VS
137{
138 if (g_isIdle)
139 wxapp_install_idle_handler();
140
48f72114 141 if (!win->m_hasVMT || !win->IsShown())
7d9f12f3
VS
142 return FALSE;
143
7d9f12f3
VS
144 int x = 0;
145 int y = 0;
146 gdk_window_get_root_origin( win->m_widget->window, &x, &y );
147 win->m_x = x;
148 win->m_y = y;
7d9f12f3
VS
149
150 wxMoveEvent mevent( wxPoint(win->m_x,win->m_y), win->GetId() );
151 mevent.SetEventObject( win );
152 win->GetEventHandler()->ProcessEvent( mevent );
153
154 return FALSE;
155}
156
d7fa7eaa
RR
157//-----------------------------------------------------------------------------
158// local code
159//-----------------------------------------------------------------------------
160
161static wxWindow* wxGetTopLevelParent(wxWindow *win)
162{
163 wxWindow *p = win;
164 while (p && !p->IsTopLevel())
165 p = p->GetParent();
166 return p;
167}
168
7d9f12f3
VS
169//-----------------------------------------------------------------------------
170// "realize" from m_widget
171//-----------------------------------------------------------------------------
172
e1f14d22
RR
173// we cannot MWM hints and icons before the widget has been realized,
174// so we do this directly after realization
7d9f12f3
VS
175
176static void
177gtk_frame_realized_callback( GtkWidget * WXUNUSED(widget), wxTopLevelWindowGTK *win )
178{
179 if (g_isIdle)
180 wxapp_install_idle_handler();
181
e1f14d22
RR
182 // All this is for Motif Window Manager "hints" and is supposed to be
183 // recognized by other WM as well. Not tested.
82c9f85c 184 gdk_window_set_decorations(win->m_widget->window,
f819b4a3 185 (GdkWMDecoration)win->m_gdkDecor);
82c9f85c 186 gdk_window_set_functions(win->m_widget->window,
f819b4a3 187 (GdkWMFunction)win->m_gdkFunc);
7d9f12f3 188
e1f14d22 189 // GTK's shrinking/growing policy
f819b4a3 190 if ((win->m_gdkFunc & GDK_FUNC_RESIZE) == 0)
7d9f12f3
VS
191 gtk_window_set_policy(GTK_WINDOW(win->m_widget), 0, 0, 1);
192 else
193 gtk_window_set_policy(GTK_WINDOW(win->m_widget), 1, 1, 1);
194
e1f14d22 195 // reset the icon
7efaed4d
MB
196 wxIconBundle iconsOld = win->GetIcons();
197 wxIcon tmp = iconsOld.GetIcon( -1 ); // operator != is not-const
198 if ( tmp != wxNullIcon )
7d9f12f3 199 {
7efaed4d 200 // wxIconBundle icon( iconOld );
7d9f12f3 201 win->SetIcon( wxNullIcon );
7efaed4d 202 win->SetIcons( iconsOld );
7d9f12f3
VS
203 }
204
d7fa7eaa
RR
205 // We need to set the focus to some child. Either, this
206 // has been done already or will be done in the next
207 // idle cycle, or we will set it ourselves.
208
209 if (g_delayedFocus)
210 {
211 if (wxGetTopLevelParent(g_delayedFocus))
212 return;
213 else
214 g_delayedFocus = NULL;
215 }
216
217 wxWindow *currentFocus = wxWindow::FindFocus();
218 if (currentFocus)
219 {
220 // I am not sure if this ever can happen,
221 // since the TLW is just about to get
222 // created and its children probably don't
223 // have any focus.
224 if (wxGetTopLevelParent(currentFocus) == win)
225 return;
226 }
227
228 // We set the focus to the child that accepts the focus.
7d9f12f3
VS
229 wxWindowList::Node *node = win->GetChildren().GetFirst();
230 while (node)
231 {
232 wxWindow *child = node->GetData();
233 if (child->AcceptsFocus())
234 {
235 child->SetFocus();
236 break;
237 }
d7fa7eaa 238
7d9f12f3
VS
239 node = node->GetNext();
240 }
241}
242
243//-----------------------------------------------------------------------------
244// "map_event" from m_widget
245//-----------------------------------------------------------------------------
246
247static void
248gtk_frame_map_callback( GtkWidget * WXUNUSED(widget),
249 GdkEvent * WXUNUSED(event),
250 wxTopLevelWindow *win )
251{
252 win->SetIconizeState(FALSE);
253}
254
255//-----------------------------------------------------------------------------
256// "unmap_event" from m_widget
257//-----------------------------------------------------------------------------
258
259static void
260gtk_frame_unmap_callback( GtkWidget * WXUNUSED(widget),
261 GdkEvent * WXUNUSED(event),
262 wxTopLevelWindow *win )
263{
264 win->SetIconizeState(TRUE);
265}
266
267//-----------------------------------------------------------------------------
268// "expose_event" of m_client
269//-----------------------------------------------------------------------------
270
271static int gtk_window_expose_callback( GtkWidget *widget, GdkEventExpose *gdk_event, wxWindow *win )
272{
273 GtkPizza *pizza = GTK_PIZZA(widget);
274
90350682
VZ
275 gtk_paint_flat_box (win->m_widget->style,
276 pizza->bin_window, GTK_STATE_NORMAL,
277 GTK_SHADOW_NONE,
278 &gdk_event->area,
279 win->m_widget,
280 (char *)"base",
281 0, 0, -1, -1);
7d9f12f3
VS
282
283 return TRUE;
284}
285
286//-----------------------------------------------------------------------------
287// "draw" of m_client
288//-----------------------------------------------------------------------------
289
52d6235d 290#ifndef __WXGTK20__
7d9f12f3
VS
291
292static void gtk_window_draw_callback( GtkWidget *widget, GdkRectangle *rect, wxWindow *win )
293{
294 GtkPizza *pizza = GTK_PIZZA(widget);
295
90350682
VZ
296 gtk_paint_flat_box (win->m_widget->style,
297 pizza->bin_window, GTK_STATE_NORMAL,
298 GTK_SHADOW_NONE,
299 rect,
300 win->m_widget,
301 (char *)"base",
302 0, 0, -1, -1);
7d9f12f3
VS
303}
304
52d6235d
VZ
305#endif // GTK+ 1.x
306
7d9f12f3
VS
307// ----------------------------------------------------------------------------
308// wxTopLevelWindowGTK itself
309// ----------------------------------------------------------------------------
310
311//-----------------------------------------------------------------------------
312// InsertChild for wxTopLevelWindowGTK
313//-----------------------------------------------------------------------------
314
315/* Callback for wxTopLevelWindowGTK. This very strange beast has to be used because
316 * C++ has no virtual methods in a constructor. We have to emulate a
317 * virtual function here as wxWindows requires different ways to insert
318 * a child in container classes. */
319
320static void wxInsertChildInTopLevelWindow( wxTopLevelWindowGTK* parent, wxWindow* child )
321{
322 wxASSERT( GTK_IS_WIDGET(child->m_widget) );
323
324 if (!parent->m_insertInClientArea)
325 {
e1f14d22 326 // these are outside the client area
7d9f12f3
VS
327 wxTopLevelWindowGTK* frame = (wxTopLevelWindowGTK*) parent;
328 gtk_pizza_put( GTK_PIZZA(frame->m_mainWidget),
329 GTK_WIDGET(child->m_widget),
330 child->m_x,
331 child->m_y,
332 child->m_width,
333 child->m_height );
334 }
335 else
336 {
e1f14d22 337 // these are inside the client area
7d9f12f3
VS
338 gtk_pizza_put( GTK_PIZZA(parent->m_wxwindow),
339 GTK_WIDGET(child->m_widget),
e4b7b2b0
VS
340 child->m_x,
341 child->m_y,
7d9f12f3
VS
342 child->m_width,
343 child->m_height );
344 }
345
e1f14d22 346 // resize on OnInternalIdle
7d9f12f3
VS
347 parent->GtkUpdateSize();
348}
349
350// ----------------------------------------------------------------------------
351// wxTopLevelWindowGTK creation
352// ----------------------------------------------------------------------------
353
354void wxTopLevelWindowGTK::Init()
355{
356 m_sizeSet = FALSE;
357 m_miniEdge = 0;
358 m_miniTitle = 0;
359 m_mainWidget = (GtkWidget*) NULL;
360 m_insertInClientArea = TRUE;
361 m_isFrame = TRUE;
362 m_isIconized = FALSE;
363 m_fsIsShowing = FALSE;
364 m_themeEnabled = TRUE;
f819b4a3 365 m_gdkDecor = m_gdkFunc = 0;
7d9f12f3
VS
366}
367
368bool wxTopLevelWindowGTK::Create( wxWindow *parent,
f819b4a3
VS
369 wxWindowID id,
370 const wxString& title,
371 const wxPoint& pos,
372 const wxSize& sizeOrig,
373 long style,
374 const wxString &name )
7d9f12f3
VS
375{
376 // always create a frame of some reasonable, even if arbitrary, size (at
377 // least for MSW compatibility)
378 wxSize size = sizeOrig;
379 if ( size.x == -1 || size.y == -1 )
380 {
381 wxSize sizeDpy = wxGetDisplaySize();
382 if ( size.x == -1 )
383 size.x = sizeDpy.x / 3;
384 if ( size.y == -1 )
385 size.y = sizeDpy.y / 5;
386 }
387
388 wxTopLevelWindows.Append( this );
389
390 m_needParent = FALSE;
2c990ec0 391
7d9f12f3
VS
392 if (!PreCreation( parent, pos, size ) ||
393 !CreateBase( parent, id, pos, size, style, wxDefaultValidator, name ))
394 {
395 wxFAIL_MSG( wxT("wxTopLevelWindowGTK creation failed") );
396 return FALSE;
397 }
398
399 m_title = title;
400
401 m_insertCallback = (wxInsertChildFunction) wxInsertChildInTopLevelWindow;
402
403 GtkWindowType win_type = GTK_WINDOW_TOPLEVEL;
404
405 if (style & wxFRAME_TOOL_WINDOW)
406 win_type = GTK_WINDOW_POPUP;
82c9f85c 407
f819b4a3 408 if (GetExtraStyle() & wxTOPLEVEL_EX_DIALOG)
9e691f46
VZ
409 {
410 // there is no more GTK_WINDOW_DIALOG in 2.0
411#ifdef __WXGTK20__
412 win_type = GTK_WINDOW_TOPLEVEL;
413#else
7d9f12f3 414 win_type = GTK_WINDOW_DIALOG;
9e691f46
VZ
415#endif
416 }
7d9f12f3
VS
417
418 m_widget = gtk_window_new( win_type );
419
7cd95599 420 if (m_parent && (GTK_IS_WINDOW(m_parent->m_widget)) &&
2c990ec0 421 (GetExtraStyle() & wxTOPLEVEL_EX_DIALOG))
7cd95599 422 {
7d9f12f3 423 gtk_window_set_transient_for( GTK_WINDOW(m_widget), GTK_WINDOW(m_parent->m_widget) );
7cd95599 424 }
7d9f12f3
VS
425
426 if (!name.IsEmpty())
427 gtk_window_set_wmclass( GTK_WINDOW(m_widget), name.mb_str(), name.mb_str() );
428
429#ifdef __WXDEBUG__
430 debug_focus_in( m_widget, wxT("wxTopLevelWindowGTK::m_widget"), name );
431#endif
432
433 gtk_window_set_title( GTK_WINDOW(m_widget), title.mbc_str() );
434 GTK_WIDGET_UNSET_FLAGS( m_widget, GTK_CAN_FOCUS );
435
436 gtk_signal_connect( GTK_OBJECT(m_widget), "delete_event",
437 GTK_SIGNAL_FUNC(gtk_frame_delete_callback), (gpointer)this );
438
e1f14d22 439 // m_mainWidget holds the toolbar, the menubar and the client area
7d9f12f3
VS
440 m_mainWidget = gtk_pizza_new();
441 gtk_widget_show( m_mainWidget );
442 GTK_WIDGET_UNSET_FLAGS( m_mainWidget, GTK_CAN_FOCUS );
443 gtk_container_add( GTK_CONTAINER(m_widget), m_mainWidget );
444
e1f14d22 445 // for m_mainWidget themes
7d9f12f3
VS
446 gtk_signal_connect( GTK_OBJECT(m_mainWidget), "expose_event",
447 GTK_SIGNAL_FUNC(gtk_window_expose_callback), (gpointer)this );
4e5a4c69 448#ifndef __WXGTK20__
7d9f12f3
VS
449 gtk_signal_connect( GTK_OBJECT(m_mainWidget), "draw",
450 GTK_SIGNAL_FUNC(gtk_window_draw_callback), (gpointer)this );
4e5a4c69 451#endif
7d9f12f3
VS
452
453#ifdef __WXDEBUG__
454 debug_focus_in( m_mainWidget, wxT("wxTopLevelWindowGTK::m_mainWidget"), name );
455#endif
456
e1f14d22 457 // m_wxwindow only represents the client area without toolbar and menubar
7d9f12f3
VS
458 m_wxwindow = gtk_pizza_new();
459 gtk_widget_show( m_wxwindow );
460 gtk_container_add( GTK_CONTAINER(m_mainWidget), m_wxwindow );
461
462#ifdef __WXDEBUG__
463 debug_focus_in( m_wxwindow, wxT("wxTopLevelWindowGTK::m_wxwindow"), name );
464#endif
465
e1f14d22
RR
466 // we donm't allow the frame to get the focus as otherwise
467 // the frame will grab it at arbitrary focus changes
7d9f12f3
VS
468 GTK_WIDGET_UNSET_FLAGS( m_wxwindow, GTK_CAN_FOCUS );
469
470 if (m_parent) m_parent->AddChild( this );
471
e1f14d22 472 // the user resized the frame by dragging etc.
7d9f12f3
VS
473 gtk_signal_connect( GTK_OBJECT(m_widget), "size_allocate",
474 GTK_SIGNAL_FUNC(gtk_frame_size_callback), (gpointer)this );
475
476 PostCreation();
477
478 if ((m_x != -1) || (m_y != -1))
479 gtk_widget_set_uposition( m_widget, m_x, m_y );
e1f14d22
RR
480
481 gtk_window_set_default_size( GTK_WINDOW(m_widget), m_width, m_height );
7d9f12f3 482
e1f14d22
RR
483 // we cannot set MWM hints and icons before the widget has
484 // been realized, so we do this directly after realization
7d9f12f3
VS
485 gtk_signal_connect( GTK_OBJECT(m_widget), "realize",
486 GTK_SIGNAL_FUNC(gtk_frame_realized_callback), (gpointer) this );
487
e1f14d22 488 // the only way to get the window size is to connect to this event
7d9f12f3
VS
489 gtk_signal_connect( GTK_OBJECT(m_widget), "configure_event",
490 GTK_SIGNAL_FUNC(gtk_frame_configure_callback), (gpointer)this );
491
e1f14d22 492 // map and unmap for iconized state
7d9f12f3
VS
493 gtk_signal_connect( GTK_OBJECT(m_widget), "map_event",
494 GTK_SIGNAL_FUNC(gtk_frame_map_callback), (gpointer)this );
495 gtk_signal_connect( GTK_OBJECT(m_widget), "unmap_event",
496 GTK_SIGNAL_FUNC(gtk_frame_unmap_callback), (gpointer)this );
497
e1f14d22 498 // the only way to get the window size is to connect to this event
7d9f12f3
VS
499 gtk_signal_connect( GTK_OBJECT(m_widget), "configure_event",
500 GTK_SIGNAL_FUNC(gtk_frame_configure_callback), (gpointer)this );
501
e1f14d22 502 // disable native tab traversal
7d9f12f3
VS
503 gtk_signal_connect( GTK_OBJECT(m_widget), "focus",
504 GTK_SIGNAL_FUNC(gtk_frame_focus_callback), (gpointer)this );
505
e1f14d22 506 // decorations
f819b4a3
VS
507 if ((m_miniEdge > 0) || (style & wxSIMPLE_BORDER) || (style & wxNO_BORDER))
508 {
509 m_gdkDecor = 0;
510 m_gdkFunc = 0;
511 }
512 else
513 {
514 m_gdkDecor = (long) GDK_DECOR_BORDER;
515 m_gdkFunc = (long) GDK_FUNC_MOVE;
82c9f85c 516
f819b4a3 517 // All this is for Motif Window Manager "hints" and is supposed to be
e1f14d22 518 // recognized by other WMs as well.
f819b4a3
VS
519 if ((style & wxCAPTION) != 0)
520 m_gdkDecor |= GDK_DECOR_TITLE;
521 if ((style & wxSYSTEM_MENU) != 0)
522 {
523 m_gdkFunc |= GDK_FUNC_CLOSE;
524 m_gdkDecor |= GDK_DECOR_MENU;
525 }
526 if ((style & wxMINIMIZE_BOX) != 0)
527 {
528 m_gdkFunc |= GDK_FUNC_MINIMIZE;
529 m_gdkDecor |= GDK_DECOR_MINIMIZE;
530 }
531 if ((style & wxMAXIMIZE_BOX) != 0)
532 {
533 m_gdkFunc |= GDK_FUNC_MAXIMIZE;
534 m_gdkDecor |= GDK_DECOR_MAXIMIZE;
535 }
536 if ((style & wxRESIZE_BORDER) != 0)
537 {
538 m_gdkFunc |= GDK_FUNC_RESIZE;
539 m_gdkDecor |= GDK_DECOR_RESIZEH;
540 }
541 }
542
7d9f12f3
VS
543 return TRUE;
544}
545
546wxTopLevelWindowGTK::~wxTopLevelWindowGTK()
547{
548 m_isBeingDeleted = TRUE;
c6ac78a6 549
710968c3
VZ
550 // it may also be GtkScrolledWindow in the case of an MDI child
551 if (GTK_IS_WINDOW(m_widget))
552 {
553 gtk_window_set_focus( GTK_WINDOW(m_widget), NULL );
554 }
7d9f12f3
VS
555
556 wxTopLevelWindows.DeleteObject( this );
557
558 if (wxTheApp->GetTopWindow() == this)
559 wxTheApp->SetTopWindow( (wxWindow*) NULL );
560
561 if ((wxTopLevelWindows.Number() == 0) &&
562 (wxTheApp->GetExitOnFrameDelete()))
563 {
564 wxTheApp->ExitMainLoop();
565 }
566}
567
568bool wxTopLevelWindowGTK::ShowFullScreen(bool show, long style )
569{
570 if (show == m_fsIsShowing) return FALSE; // return what?
571
572 m_fsIsShowing = show;
573
574 if (show)
575 {
82f2d919
VS
576 m_fsSaveGdkFunc = m_gdkFunc;
577 m_fsSaveGdkDecor = m_gdkDecor;
7d9f12f3
VS
578 m_fsSaveFlag = style;
579 GetPosition( &m_fsSaveFrame.x, &m_fsSaveFrame.y );
580 GetSize( &m_fsSaveFrame.width, &m_fsSaveFrame.height );
581
582 gtk_widget_hide( m_widget );
583 gtk_widget_unrealize( m_widget );
584
82f2d919
VS
585 m_gdkDecor = (long) GDK_DECOR_BORDER;
586 m_gdkFunc = (long) GDK_FUNC_MOVE;
7d9f12f3
VS
587
588 int x;
589 int y;
590 wxDisplaySize( &x, &y );
591 SetSize( 0, 0, x, y );
592
593 gtk_widget_realize( m_widget );
594 gtk_widget_show( m_widget );
595 }
596 else
597 {
598 gtk_widget_hide( m_widget );
599 gtk_widget_unrealize( m_widget );
600
82f2d919
VS
601 m_gdkFunc = m_fsSaveGdkFunc;
602 m_gdkDecor = m_fsSaveGdkDecor;
7d9f12f3
VS
603
604 SetSize( m_fsSaveFrame.x, m_fsSaveFrame.y, m_fsSaveFrame.width, m_fsSaveFrame.height );
605
606 gtk_widget_realize( m_widget );
607 gtk_widget_show( m_widget );
608 }
609
610 return TRUE;
611}
612
613// ----------------------------------------------------------------------------
614// overridden wxWindow methods
615// ----------------------------------------------------------------------------
616
617bool wxTopLevelWindowGTK::Show( bool show )
618{
619 wxASSERT_MSG( (m_widget != NULL), wxT("invalid frame") );
620
621 if (show && !m_sizeSet)
622 {
623 /* by calling GtkOnSize here, we don't have to call
624 either after showing the frame, which would entail
625 much ugly flicker or from within the size_allocate
626 handler, because GTK 1.1.X forbids that. */
627
628 GtkOnSize( m_x, m_y, m_width, m_height );
629 }
630
631 return wxWindow::Show( show );
632}
633
634void wxTopLevelWindowGTK::DoMoveWindow(int WXUNUSED(x), int WXUNUSED(y), int WXUNUSED(width), int WXUNUSED(height) )
635{
636 wxFAIL_MSG( wxT("DoMoveWindow called for wxTopLevelWindowGTK") );
637}
638
639void wxTopLevelWindowGTK::DoSetSize( int x, int y, int width, int height, int sizeFlags )
640{
641 wxASSERT_MSG( (m_widget != NULL), wxT("invalid frame") );
642
e1f14d22 643 // this shouldn't happen: wxFrame, wxMDIParentFrame and wxMDIChildFrame have m_wxwindow
7d9f12f3
VS
644 wxASSERT_MSG( (m_wxwindow != NULL), wxT("invalid frame") );
645
e1f14d22 646 // avoid recursions
7d9f12f3
VS
647 if (m_resizing)
648 return;
649 m_resizing = TRUE;
650
651 int old_x = m_x;
652 int old_y = m_y;
653
654 int old_width = m_width;
655 int old_height = m_height;
656
657 if ((sizeFlags & wxSIZE_ALLOW_MINUS_ONE) == 0)
658 {
659 if (x != -1) m_x = x;
660 if (y != -1) m_y = y;
661 if (width != -1) m_width = width;
662 if (height != -1) m_height = height;
663 }
664 else
665 {
666 m_x = x;
667 m_y = y;
668 m_width = width;
669 m_height = height;
670 }
671
672/*
673 if ((sizeFlags & wxSIZE_AUTO_WIDTH) == wxSIZE_AUTO_WIDTH)
674 {
675 if (width == -1) m_width = 80;
676 }
677
678 if ((sizeFlags & wxSIZE_AUTO_HEIGHT) == wxSIZE_AUTO_HEIGHT)
679 {
680 if (height == -1) m_height = 26;
681 }
682*/
683
e7dda1ff
VS
684 int minWidth = GetMinWidth(),
685 minHeight = GetMinHeight(),
686 maxWidth = GetMaxWidth(),
687 maxHeight = GetMaxHeight();
688
689 if ((minWidth != -1) && (m_width < minWidth)) m_width = minWidth;
690 if ((minHeight != -1) && (m_height < minHeight)) m_height = minHeight;
691 if ((maxWidth != -1) && (m_width > maxWidth)) m_width = maxWidth;
692 if ((maxHeight != -1) && (m_height > maxHeight)) m_height = maxHeight;
7d9f12f3
VS
693
694 if ((m_x != -1) || (m_y != -1))
695 {
696 if ((m_x != old_x) || (m_y != old_y))
697 {
698 gtk_widget_set_uposition( m_widget, m_x, m_y );
699 }
700 }
701
702 if ((m_width != old_width) || (m_height != old_height))
703 {
e1f14d22
RR
704 if (m_widget->window)
705 gdk_window_resize( m_widget->window, m_width, m_height );
706 else
707 gtk_window_set_default_size( GTK_WINDOW(m_widget), m_width, m_height );
7d9f12f3
VS
708
709 /* we set the size in GtkOnSize, i.e. mostly the actual resizing is
710 done either directly before the frame is shown or in idle time
711 so that different calls to SetSize() don't lead to flicker. */
712 m_sizeSet = FALSE;
713 }
714
715 m_resizing = FALSE;
716}
717
718void wxTopLevelWindowGTK::DoGetClientSize( int *width, int *height ) const
719{
720 wxASSERT_MSG( (m_widget != NULL), wxT("invalid frame") );
721
722 wxWindow::DoGetClientSize( width, height );
723 if (height)
724 {
e1f14d22 725 // mini edge
7d9f12f3
VS
726 *height -= m_miniEdge*2 + m_miniTitle;
727 }
728 if (width)
729 {
730 *width -= m_miniEdge*2;
731 }
732}
733
734void wxTopLevelWindowGTK::DoSetClientSize( int width, int height )
735{
736 wxASSERT_MSG( (m_widget != NULL), wxT("invalid frame") );
737
82c9f85c 738 DoSetSize(-1, -1,
7d9f12f3
VS
739 width + m_miniEdge*2, height + m_miniEdge*2 + m_miniTitle, 0);
740}
741
742void wxTopLevelWindowGTK::GtkOnSize( int WXUNUSED(x), int WXUNUSED(y),
82c9f85c 743 int width, int height )
7d9f12f3
VS
744{
745 // due to a bug in gtk, x,y are always 0
746 // m_x = x;
747 // m_y = y;
748
e1f14d22 749 // avoid recursions
7d9f12f3
VS
750 if (m_resizing) return;
751 m_resizing = TRUE;
752
753 if ( m_wxwindow == NULL ) return;
754
755 m_width = width;
756 m_height = height;
757
0d53fc34 758 /* wxMDIChildFrame derives from wxFrame but it _is_ a wxWindow as it uses
7d9f12f3 759 wxWindow::Create to create it's GTK equivalent. m_mainWidget is only
0d53fc34 760 set in wxFrame::Create so it is used to check what kind of frame we
7d9f12f3
VS
761 have here. if m_mainWidget is NULL it is a wxMDIChildFrame and so we
762 skip the part which handles m_frameMenuBar, m_frameToolBar and (most
763 importantly) m_mainWidget */
764
e7dda1ff
VS
765 int minWidth = GetMinWidth(),
766 minHeight = GetMinHeight(),
767 maxWidth = GetMaxWidth(),
768 maxHeight = GetMaxHeight();
769
770 if ((minWidth != -1) && (m_width < minWidth)) m_width = minWidth;
771 if ((minHeight != -1) && (m_height < minHeight)) m_height = minHeight;
772 if ((maxWidth != -1) && (m_width > maxWidth)) m_width = maxWidth;
773 if ((maxHeight != -1) && (m_height > maxHeight)) m_height = maxHeight;
7d9f12f3
VS
774
775 if (m_mainWidget)
776 {
e1f14d22 777 // set size hints
7d9f12f3 778 gint flag = 0; // GDK_HINT_POS;
e7dda1ff
VS
779 if ((minWidth != -1) || (minHeight != -1)) flag |= GDK_HINT_MIN_SIZE;
780 if ((maxWidth != -1) || (maxHeight != -1)) flag |= GDK_HINT_MAX_SIZE;
7d9f12f3 781 GdkGeometry geom;
e7dda1ff
VS
782 geom.min_width = minWidth;
783 geom.min_height = minHeight;
784 geom.max_width = maxWidth;
785 geom.max_height = maxHeight;
7d9f12f3
VS
786 gtk_window_set_geometry_hints( GTK_WINDOW(m_widget),
787 (GtkWidget*) NULL,
788 &geom,
789 (GdkWindowHints) flag );
790
791 /* I revert back to wxGTK's original behaviour. m_mainWidget holds the
792 * menubar, the toolbar and the client area, which is represented by
793 * m_wxwindow.
794 * this hurts in the eye, but I don't want to call SetSize()
795 * because I don't want to call any non-native functions here. */
796
797 int client_x = m_miniEdge;
798 int client_y = m_miniEdge + m_miniTitle;
799 int client_w = m_width - 2*m_miniEdge;
800 int client_h = m_height - 2*m_miniEdge - m_miniTitle;
801 gtk_pizza_set_size( GTK_PIZZA(m_mainWidget),
802 m_wxwindow,
803 client_x, client_y, client_w, client_h );
804 }
805 else
806 {
e1f14d22
RR
807 // If there is no m_mainWidget between m_widget and m_wxwindow there
808 // is no need to set the size or position of m_wxwindow.
7d9f12f3
VS
809 }
810
811 m_sizeSet = TRUE;
812
813 // send size event to frame
814 wxSizeEvent event( wxSize(m_width,m_height), GetId() );
815 event.SetEventObject( this );
816 GetEventHandler()->ProcessEvent( event );
817
818 m_resizing = FALSE;
819}
820
821void wxTopLevelWindowGTK::OnInternalIdle()
822{
823 if (!m_sizeSet && GTK_WIDGET_REALIZED(m_wxwindow))
824 {
825 GtkOnSize( m_x, m_y, m_width, m_height );
826
827 // we'll come back later
828 if (g_isIdle)
829 wxapp_install_idle_handler();
830 return;
831 }
832
833 wxWindow::OnInternalIdle();
834}
835
836
837// ----------------------------------------------------------------------------
838// frame title/icon
839// ----------------------------------------------------------------------------
840
841void wxTopLevelWindowGTK::SetTitle( const wxString &title )
842{
843 wxASSERT_MSG( (m_widget != NULL), wxT("invalid frame") );
844
845 m_title = title;
846 gtk_window_set_title( GTK_WINDOW(m_widget), title.mbc_str() );
847}
848
f618020a 849void wxTopLevelWindowGTK::DoSetIcon( const wxIcon &icon )
7d9f12f3 850{
f618020a 851 if ( !icon.Ok() )
7d9f12f3
VS
852 return;
853
854 if (!m_widget->window)
855 return;
856
857 wxMask *mask = icon.GetMask();
858 GdkBitmap *bm = (GdkBitmap *) NULL;
859 if (mask) bm = mask->GetBitmap();
860
861 gdk_window_set_icon( m_widget->window, (GdkWindow *) NULL, icon.GetPixmap(), bm );
862}
863
f618020a
MB
864void wxTopLevelWindowGTK::SetIcon( const wxIcon &icon )
865{
866 SetIcons( wxIconBundle( icon ) );
867}
868
869void wxTopLevelWindowGTK::SetIcons( const wxIconBundle &icons )
870{
871 wxASSERT_MSG( (m_widget != NULL), wxT("invalid frame") );
872 GdkWindow* window = m_widget->window;
f618020a
MB
873
874 wxTopLevelWindowBase::SetIcons( icons );
875
876 DoSetIcon( icons.GetIcon( -1 ) );
52d6235d
VZ
877 if ( window )
878 {
7efaed4d
MB
879 wxSetIconsX11( (WXDisplay*)GDK_WINDOW_XDISPLAY( window ),
880 (WXWindow)GDK_WINDOW_XWINDOW( window ), icons );
52d6235d 881 }
f618020a
MB
882}
883
7d9f12f3
VS
884// ----------------------------------------------------------------------------
885// frame state: maximized/iconized/normal
886// ----------------------------------------------------------------------------
887
888void wxTopLevelWindowGTK::Maximize(bool WXUNUSED(maximize))
889{
890 wxFAIL_MSG( _T("not implemented") );
891}
892
893bool wxTopLevelWindowGTK::IsMaximized() const
894{
895 // wxFAIL_MSG( _T("not implemented") );
896
897 // This is an approximation
898 return FALSE;
899}
900
901void wxTopLevelWindowGTK::Restore()
902{
903 wxFAIL_MSG( _T("not implemented") );
904}
905
906void wxTopLevelWindowGTK::Iconize( bool iconize )
907{
908 if (iconize)
909 {
910 GdkWindow *window = m_widget->window;
911
912 // you should do it later, for example from OnCreate() handler
913 wxCHECK_RET( window, _T("frame not created yet - can't iconize") );
914
915 XIconifyWindow( GDK_WINDOW_XDISPLAY( window ),
916 GDK_WINDOW_XWINDOW( window ),
917 DefaultScreen( GDK_DISPLAY() ) );
918 }
919}
920
921bool wxTopLevelWindowGTK::IsIconized() const
922{
923 return m_isIconized;
924}
925
926void wxTopLevelWindowGTK::SetIconizeState(bool iconize)
927{
928 if ( iconize != m_isIconized )
929 {
930 m_isIconized = iconize;
931 (void)SendIconizeEvent(iconize);
932 }
933}
934