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