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