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