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