]> git.saurik.com Git - wxWidgets.git/blame - src/gtk/toplevel.cpp
According to Stefan Neis this file isn't used by anything other than
[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
65571936 7// Licence: wxWindows licence
7d9f12f3
VS
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;
7d9f12f3
VS
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
77ffb593 267 * virtual function here as wxWidgets requires different ways to insert
7d9f12f3
VS
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;
1111cedc 329 size.x = WidthDefault(size.x);
66202a7e 330 size.y = HeightDefault(size.y);
7d9f12f3
VS
331
332 wxTopLevelWindows.Append( this );
333
334 m_needParent = FALSE;
6aeb6f2a 335
7d9f12f3
VS
336 if (!PreCreation( parent, pos, size ) ||
337 !CreateBase( parent, id, pos, size, style, wxDefaultValidator, name ))
338 {
339 wxFAIL_MSG( wxT("wxTopLevelWindowGTK creation failed") );
340 return FALSE;
341 }
342
343 m_title = title;
344
345 m_insertCallback = (wxInsertChildFunction) wxInsertChildInTopLevelWindow;
346
63c5efa3
VS
347 // NB: m_widget may be !=NULL if it was created by derived class' Create,
348 // e.g. in wxTaskBarIconAreaGTK
349 if (m_widget == NULL)
350 {
351 GtkWindowType win_type = GTK_WINDOW_TOPLEVEL;
63c5efa3
VS
352 if (style & wxFRAME_TOOL_WINDOW)
353 win_type = GTK_WINDOW_POPUP;
82c9f85c 354
63c5efa3
VS
355 if (GetExtraStyle() & wxTOPLEVEL_EX_DIALOG)
356 {
9e691f46 357#ifdef __WXGTK20__
4d8d6490
VS
358 m_widget = gtk_window_new(GTK_WINDOW_TOPLEVEL);
359 // Tell WM that this is a dialog window and make it center
360 // on parent by default (this is what GtkDialog ctor does):
361 gtk_window_set_type_hint(GTK_WINDOW(m_widget),
362 GDK_WINDOW_TYPE_HINT_DIALOG);
363 gtk_window_set_position(GTK_WINDOW(m_widget),
364 GTK_WIN_POS_CENTER_ON_PARENT);
9e691f46 365#else
4d8d6490 366 m_widget = gtk_window_new(GTK_WINDOW_DIALOG);
9e691f46 367#endif
63c5efa3 368 }
4d8d6490
VS
369 else
370 {
371 m_widget = gtk_window_new(win_type);
372 }
63c5efa3 373 }
7d9f12f3 374
50819679
JS
375 if (m_parent && (((GTK_IS_WINDOW(m_parent->m_widget)) &&
376 (GetExtraStyle() & wxTOPLEVEL_EX_DIALOG)) ||
377 (style & wxFRAME_FLOAT_ON_PARENT)))
7cd95599 378 {
7d9f12f3 379 gtk_window_set_transient_for( GTK_WINDOW(m_widget), GTK_WINDOW(m_parent->m_widget) );
7cd95599 380 }
7d9f12f3 381
2be125e6
VS
382#if GTK_CHECK_VERSION(2,2,0)
383 if (style & wxFRAME_NO_TASKBAR)
384 {
385 gtk_window_set_skip_taskbar_hint(GTK_WINDOW(m_widget), TRUE);
386 }
387#endif
388
7d9f12f3 389 if (!name.IsEmpty())
fab591c5 390 gtk_window_set_wmclass( GTK_WINDOW(m_widget), wxGTK_CONV( name ), wxGTK_CONV( name ) );
7d9f12f3 391
fab591c5 392 gtk_window_set_title( GTK_WINDOW(m_widget), wxGTK_CONV( title ) );
7d9f12f3
VS
393 GTK_WIDGET_UNSET_FLAGS( m_widget, GTK_CAN_FOCUS );
394
395 gtk_signal_connect( GTK_OBJECT(m_widget), "delete_event",
396 GTK_SIGNAL_FUNC(gtk_frame_delete_callback), (gpointer)this );
397
e1f14d22 398 // m_mainWidget holds the toolbar, the menubar and the client area
7d9f12f3
VS
399 m_mainWidget = gtk_pizza_new();
400 gtk_widget_show( m_mainWidget );
401 GTK_WIDGET_UNSET_FLAGS( m_mainWidget, GTK_CAN_FOCUS );
402 gtk_container_add( GTK_CONTAINER(m_widget), m_mainWidget );
403
cba9ef7f
RR
404 if (m_miniEdge == 0) // wxMiniFrame has its own version.
405 {
406 // For m_mainWidget themes
407 gtk_signal_connect( GTK_OBJECT(m_mainWidget), "expose_event",
7d9f12f3 408 GTK_SIGNAL_FUNC(gtk_window_expose_callback), (gpointer)this );
4e5a4c69 409#ifndef __WXGTK20__
cba9ef7f 410 gtk_signal_connect( GTK_OBJECT(m_mainWidget), "draw",
7d9f12f3 411 GTK_SIGNAL_FUNC(gtk_window_draw_callback), (gpointer)this );
4e5a4c69 412#endif
cba9ef7f 413 }
7d9f12f3 414
e1f14d22 415 // m_wxwindow only represents the client area without toolbar and menubar
7d9f12f3
VS
416 m_wxwindow = gtk_pizza_new();
417 gtk_widget_show( m_wxwindow );
418 gtk_container_add( GTK_CONTAINER(m_mainWidget), m_wxwindow );
419
e1f14d22
RR
420 // we donm't allow the frame to get the focus as otherwise
421 // the frame will grab it at arbitrary focus changes
7d9f12f3
VS
422 GTK_WIDGET_UNSET_FLAGS( m_wxwindow, GTK_CAN_FOCUS );
423
424 if (m_parent) m_parent->AddChild( this );
425
e1f14d22 426 // the user resized the frame by dragging etc.
7d9f12f3
VS
427 gtk_signal_connect( GTK_OBJECT(m_widget), "size_allocate",
428 GTK_SIGNAL_FUNC(gtk_frame_size_callback), (gpointer)this );
429
430 PostCreation();
431
432 if ((m_x != -1) || (m_y != -1))
433 gtk_widget_set_uposition( m_widget, m_x, m_y );
6aeb6f2a 434
e1f14d22 435 gtk_window_set_default_size( GTK_WINDOW(m_widget), m_width, m_height );
7d9f12f3 436
e1f14d22
RR
437 // we cannot set MWM hints and icons before the widget has
438 // been realized, so we do this directly after realization
7d9f12f3
VS
439 gtk_signal_connect( GTK_OBJECT(m_widget), "realize",
440 GTK_SIGNAL_FUNC(gtk_frame_realized_callback), (gpointer) this );
441
e1f14d22 442 // the only way to get the window size is to connect to this event
7d9f12f3
VS
443 gtk_signal_connect( GTK_OBJECT(m_widget), "configure_event",
444 GTK_SIGNAL_FUNC(gtk_frame_configure_callback), (gpointer)this );
445
e1f14d22 446 // map and unmap for iconized state
7d9f12f3
VS
447 gtk_signal_connect( GTK_OBJECT(m_widget), "map_event",
448 GTK_SIGNAL_FUNC(gtk_frame_map_callback), (gpointer)this );
449 gtk_signal_connect( GTK_OBJECT(m_widget), "unmap_event",
450 GTK_SIGNAL_FUNC(gtk_frame_unmap_callback), (gpointer)this );
451
e1f14d22 452 // the only way to get the window size is to connect to this event
7d9f12f3
VS
453 gtk_signal_connect( GTK_OBJECT(m_widget), "configure_event",
454 GTK_SIGNAL_FUNC(gtk_frame_configure_callback), (gpointer)this );
455
e1f14d22 456 // disable native tab traversal
7d9f12f3
VS
457 gtk_signal_connect( GTK_OBJECT(m_widget), "focus",
458 GTK_SIGNAL_FUNC(gtk_frame_focus_callback), (gpointer)this );
459
e1f14d22 460 // decorations
f819b4a3
VS
461 if ((m_miniEdge > 0) || (style & wxSIMPLE_BORDER) || (style & wxNO_BORDER))
462 {
463 m_gdkDecor = 0;
464 m_gdkFunc = 0;
465 }
466 else
467 {
468 m_gdkDecor = (long) GDK_DECOR_BORDER;
469 m_gdkFunc = (long) GDK_FUNC_MOVE;
82c9f85c 470
f819b4a3 471 // All this is for Motif Window Manager "hints" and is supposed to be
e1f14d22 472 // recognized by other WMs as well.
f819b4a3 473 if ((style & wxCAPTION) != 0)
c3d8ee42 474 {
f819b4a3 475 m_gdkDecor |= GDK_DECOR_TITLE;
c3d8ee42 476 }
850c6ed4 477 if ((style & wxCLOSE_BOX) != 0)
f819b4a3
VS
478 {
479 m_gdkFunc |= GDK_FUNC_CLOSE;
c3d8ee42
VS
480 }
481 if ((style & wxSYSTEM_MENU) != 0)
482 {
f819b4a3
VS
483 m_gdkDecor |= GDK_DECOR_MENU;
484 }
485 if ((style & wxMINIMIZE_BOX) != 0)
486 {
487 m_gdkFunc |= GDK_FUNC_MINIMIZE;
488 m_gdkDecor |= GDK_DECOR_MINIMIZE;
489 }
490 if ((style & wxMAXIMIZE_BOX) != 0)
491 {
492 m_gdkFunc |= GDK_FUNC_MAXIMIZE;
493 m_gdkDecor |= GDK_DECOR_MAXIMIZE;
494 }
495 if ((style & wxRESIZE_BORDER) != 0)
496 {
497 m_gdkFunc |= GDK_FUNC_RESIZE;
498 m_gdkDecor |= GDK_DECOR_RESIZEH;
499 }
500 }
501
7d9f12f3
VS
502 return TRUE;
503}
504
505wxTopLevelWindowGTK::~wxTopLevelWindowGTK()
506{
5152b0e5
JS
507 if (m_grabbed)
508 {
83afe211 509 wxASSERT_MSG( FALSE, _T("Window still grabbed"));
5152b0e5
JS
510 RemoveGrab();
511 }
1cbee0b4 512
7d9f12f3 513 m_isBeingDeleted = TRUE;
6aeb6f2a 514
710968c3
VZ
515 // it may also be GtkScrolledWindow in the case of an MDI child
516 if (GTK_IS_WINDOW(m_widget))
517 {
518 gtk_window_set_focus( GTK_WINDOW(m_widget), NULL );
519 }
7d9f12f3
VS
520}
521
8a9650ea 522
8a9650ea 523
7d9f12f3
VS
524bool wxTopLevelWindowGTK::ShowFullScreen(bool show, long style )
525{
526 if (show == m_fsIsShowing) return FALSE; // return what?
527
528 m_fsIsShowing = show;
529
8166ab43 530 GdkWindow *window = m_widget->window;
1542ea39 531 wxX11FullScreenMethod method =
8166ab43
VS
532 wxGetFullScreenMethodX11((WXDisplay*)GDK_DISPLAY(),
533 (WXWindow)GDK_ROOT_WINDOW());
1542ea39 534
7d9f12f3
VS
535 if (show)
536 {
7d9f12f3
VS
537 m_fsSaveFlag = style;
538 GetPosition( &m_fsSaveFrame.x, &m_fsSaveFrame.y );
539 GetSize( &m_fsSaveFrame.width, &m_fsSaveFrame.height );
540
8a9650ea
RR
541 int screen_width,screen_height;
542 wxDisplaySize( &screen_width, &screen_height );
1cbee0b4 543
8a9650ea
RR
544 gint client_x, client_y, root_x, root_y;
545 gint width, height;
7d9f12f3 546
1cff04de 547 if (method != wxX11_FS_WMSPEC)
8166ab43
VS
548 {
549 // don't do it always, Metacity hates it
550 m_fsSaveGdkFunc = m_gdkFunc;
551 m_fsSaveGdkDecor = m_gdkDecor;
552 m_gdkFunc = m_gdkDecor = 0;
553 gdk_window_set_decorations(window, (GdkWMDecoration)0);
554 gdk_window_set_functions(window, (GdkWMFunction)0);
555 }
1542ea39 556
8a9650ea
RR
557 gdk_window_get_origin (m_widget->window, &root_x, &root_y);
558 gdk_window_get_geometry (m_widget->window, &client_x, &client_y,
559 &width, &height, NULL);
1cbee0b4 560
8a9650ea
RR
561 gdk_window_move_resize (m_widget->window, -client_x, -client_y,
562 screen_width + 1, screen_height + 1);
8166ab43
VS
563
564 wxSetFullScreenStateX11((WXDisplay*)GDK_DISPLAY(),
565 (WXWindow)GDK_ROOT_WINDOW(),
566 (WXWindow)GDK_WINDOW_XWINDOW(window),
567 show, &m_fsSaveFrame, method);
7d9f12f3
VS
568 }
569 else
570 {
1cff04de 571 if (method != wxX11_FS_WMSPEC)
8166ab43
VS
572 {
573 // don't do it always, Metacity hates it
574 m_gdkFunc = m_fsSaveGdkFunc;
575 m_gdkDecor = m_fsSaveGdkDecor;
576 gdk_window_set_decorations(window, (GdkWMDecoration)m_gdkDecor);
577 gdk_window_set_functions(window, (GdkWMFunction)m_gdkFunc);
578 }
1542ea39 579
8166ab43
VS
580 wxSetFullScreenStateX11((WXDisplay*)GDK_DISPLAY(),
581 (WXWindow)GDK_ROOT_WINDOW(),
582 (WXWindow)GDK_WINDOW_XWINDOW(window),
583 show, &m_fsSaveFrame, method);
1542ea39 584
8166ab43
VS
585 SetSize(m_fsSaveFrame.x, m_fsSaveFrame.y,
586 m_fsSaveFrame.width, m_fsSaveFrame.height);
7d9f12f3
VS
587 }
588
8166ab43 589
7d9f12f3
VS
590 return TRUE;
591}
592
593// ----------------------------------------------------------------------------
594// overridden wxWindow methods
595// ----------------------------------------------------------------------------
596
597bool wxTopLevelWindowGTK::Show( bool show )
598{
82b978d7 599 wxASSERT_MSG( (m_widget != NULL), wxT("invalid frame") );
7d9f12f3
VS
600
601 if (show && !m_sizeSet)
602 {
603 /* by calling GtkOnSize here, we don't have to call
604 either after showing the frame, which would entail
605 much ugly flicker or from within the size_allocate
606 handler, because GTK 1.1.X forbids that. */
607
608 GtkOnSize( m_x, m_y, m_width, m_height );
609 }
610
611 return wxWindow::Show( show );
612}
613
614void wxTopLevelWindowGTK::DoMoveWindow(int WXUNUSED(x), int WXUNUSED(y), int WXUNUSED(width), int WXUNUSED(height) )
615{
616 wxFAIL_MSG( wxT("DoMoveWindow called for wxTopLevelWindowGTK") );
617}
618
619void wxTopLevelWindowGTK::DoSetSize( int x, int y, int width, int height, int sizeFlags )
620{
82b978d7
RD
621 wxASSERT_MSG( (m_widget != NULL), wxT("invalid frame") );
622
e1f14d22 623 // this shouldn't happen: wxFrame, wxMDIParentFrame and wxMDIChildFrame have m_wxwindow
7d9f12f3
VS
624 wxASSERT_MSG( (m_wxwindow != NULL), wxT("invalid frame") );
625
e1f14d22 626 // avoid recursions
7d9f12f3
VS
627 if (m_resizing)
628 return;
629 m_resizing = TRUE;
630
631 int old_x = m_x;
632 int old_y = m_y;
633
634 int old_width = m_width;
635 int old_height = m_height;
636
637 if ((sizeFlags & wxSIZE_ALLOW_MINUS_ONE) == 0)
638 {
639 if (x != -1) m_x = x;
640 if (y != -1) m_y = y;
7d9f12f3
VS
641 }
642 else
643 {
644 m_x = x;
645 m_y = y;
7d9f12f3 646 }
d44c23ce
RR
647 if (width != -1) m_width = width;
648 if (height != -1) m_height = height;
7d9f12f3
VS
649
650/*
651 if ((sizeFlags & wxSIZE_AUTO_WIDTH) == wxSIZE_AUTO_WIDTH)
652 {
653 if (width == -1) m_width = 80;
654 }
655
656 if ((sizeFlags & wxSIZE_AUTO_HEIGHT) == wxSIZE_AUTO_HEIGHT)
657 {
658 if (height == -1) m_height = 26;
659 }
660*/
661
e7dda1ff
VS
662 int minWidth = GetMinWidth(),
663 minHeight = GetMinHeight(),
664 maxWidth = GetMaxWidth(),
665 maxHeight = GetMaxHeight();
666
62be94e1
RR
667#ifdef __WXGPE__
668 // GPE's window manager doesn't like size hints
669 // at all, esp. when the user has to use the
670 // virtual keyboard.
671 minWidth = -1;
672 minHeight = -1;
673 maxWidth = -1;
674 maxHeight = -1;
675#endif
ca06ee0d 676
e7dda1ff
VS
677 if ((minWidth != -1) && (m_width < minWidth)) m_width = minWidth;
678 if ((minHeight != -1) && (m_height < minHeight)) m_height = minHeight;
679 if ((maxWidth != -1) && (m_width > maxWidth)) m_width = maxWidth;
680 if ((maxHeight != -1) && (m_height > maxHeight)) m_height = maxHeight;
7d9f12f3
VS
681
682 if ((m_x != -1) || (m_y != -1))
683 {
684 if ((m_x != old_x) || (m_y != old_y))
685 {
686 gtk_widget_set_uposition( m_widget, m_x, m_y );
687 }
688 }
689
690 if ((m_width != old_width) || (m_height != old_height))
691 {
e1f14d22
RR
692 if (m_widget->window)
693 gdk_window_resize( m_widget->window, m_width, m_height );
694 else
695 gtk_window_set_default_size( GTK_WINDOW(m_widget), m_width, m_height );
7d9f12f3
VS
696
697 /* we set the size in GtkOnSize, i.e. mostly the actual resizing is
698 done either directly before the frame is shown or in idle time
699 so that different calls to SetSize() don't lead to flicker. */
700 m_sizeSet = FALSE;
701 }
702
703 m_resizing = FALSE;
704}
705
706void wxTopLevelWindowGTK::DoGetClientSize( int *width, int *height ) const
707{
82b978d7
RD
708 wxASSERT_MSG( (m_widget != NULL), wxT("invalid frame") );
709
7d9f12f3
VS
710 wxWindow::DoGetClientSize( width, height );
711 if (height)
712 {
e1f14d22 713 // mini edge
7d9f12f3
VS
714 *height -= m_miniEdge*2 + m_miniTitle;
715 }
716 if (width)
717 {
718 *width -= m_miniEdge*2;
719 }
720}
721
722void wxTopLevelWindowGTK::DoSetClientSize( int width, int height )
723{
82b978d7 724 wxASSERT_MSG( (m_widget != NULL), wxT("invalid frame") );
7d9f12f3 725
82c9f85c 726 DoSetSize(-1, -1,
7d9f12f3
VS
727 width + m_miniEdge*2, height + m_miniEdge*2 + m_miniTitle, 0);
728}
729
730void wxTopLevelWindowGTK::GtkOnSize( int WXUNUSED(x), int WXUNUSED(y),
82c9f85c 731 int width, int height )
7d9f12f3
VS
732{
733 // due to a bug in gtk, x,y are always 0
734 // m_x = x;
735 // m_y = y;
736
e1f14d22 737 // avoid recursions
7d9f12f3
VS
738 if (m_resizing) return;
739 m_resizing = TRUE;
740
741 if ( m_wxwindow == NULL ) return;
742
743 m_width = width;
744 m_height = height;
745
0d53fc34 746 /* wxMDIChildFrame derives from wxFrame but it _is_ a wxWindow as it uses
7d9f12f3 747 wxWindow::Create to create it's GTK equivalent. m_mainWidget is only
0d53fc34 748 set in wxFrame::Create so it is used to check what kind of frame we
7d9f12f3
VS
749 have here. if m_mainWidget is NULL it is a wxMDIChildFrame and so we
750 skip the part which handles m_frameMenuBar, m_frameToolBar and (most
751 importantly) m_mainWidget */
752
e7dda1ff
VS
753 int minWidth = GetMinWidth(),
754 minHeight = GetMinHeight(),
755 maxWidth = GetMaxWidth(),
756 maxHeight = GetMaxHeight();
757
62be94e1
RR
758#ifdef __WXGPE__
759 // GPE's window manager doesn't like size hints
760 // at all, esp. when the user has to use the
761 // virtual keyboard.
762 minWidth = -1;
763 minHeight = -1;
764 maxWidth = -1;
765 maxHeight = -1;
766#endif
ca06ee0d 767
e7dda1ff
VS
768 if ((minWidth != -1) && (m_width < minWidth)) m_width = minWidth;
769 if ((minHeight != -1) && (m_height < minHeight)) m_height = minHeight;
770 if ((maxWidth != -1) && (m_width > maxWidth)) m_width = maxWidth;
771 if ((maxHeight != -1) && (m_height > maxHeight)) m_height = maxHeight;
7d9f12f3
VS
772
773 if (m_mainWidget)
774 {
e1f14d22 775 // set size hints
801225c1
RL
776 gint flag = 0; // GDK_HINT_POS;
777 GdkGeometry geom;
778
e7dda1ff
VS
779 if ((minWidth != -1) || (minHeight != -1)) flag |= GDK_HINT_MIN_SIZE;
780 if ((maxWidth != -1) || (maxHeight != -1)) flag |= GDK_HINT_MAX_SIZE;
801225c1 781
e7dda1ff
VS
782 geom.min_width = minWidth;
783 geom.min_height = minHeight;
801225c1
RL
784
785 // Because of the way we set GDK_HINT_MAX_SIZE above, if either of
786 // maxHeight or maxWidth is set, we must set them both, else the
787 // remaining -1 will be taken literally.
788
789 // I'm certain this also happens elsewhere, and is the probable
790 // cause of other such things as:
791 // Gtk-WARNING **: gtk_widget_size_allocate():
792 // attempt to allocate widget with width 65535 and height 600
793 // but I don't have time to track them all now..
1cbee0b4 794 //
801225c1
RL
795 // Really we need to encapulate all this height/width business and
796 // stop any old method from ripping at the members directly and
797 // scattering -1's without regard for who might resolve them later.
798
799 geom.max_width = ( maxHeight == -1 ) ? maxWidth
800 : ( maxWidth == -1 ) ? wxGetDisplaySize().GetWidth()
801 : maxWidth ;
802
803 geom.max_height = ( maxWidth == -1 ) ? maxHeight // ( == -1 here )
804 : ( maxHeight == -1 ) ? wxGetDisplaySize().GetHeight()
805 : maxHeight ;
806
7d9f12f3
VS
807 gtk_window_set_geometry_hints( GTK_WINDOW(m_widget),
808 (GtkWidget*) NULL,
809 &geom,
810 (GdkWindowHints) flag );
811
812 /* I revert back to wxGTK's original behaviour. m_mainWidget holds the
813 * menubar, the toolbar and the client area, which is represented by
814 * m_wxwindow.
815 * this hurts in the eye, but I don't want to call SetSize()
816 * because I don't want to call any non-native functions here. */
817
818 int client_x = m_miniEdge;
819 int client_y = m_miniEdge + m_miniTitle;
820 int client_w = m_width - 2*m_miniEdge;
821 int client_h = m_height - 2*m_miniEdge - m_miniTitle;
801225c1 822
7d9f12f3
VS
823 gtk_pizza_set_size( GTK_PIZZA(m_mainWidget),
824 m_wxwindow,
825 client_x, client_y, client_w, client_h );
826 }
827 else
828 {
e1f14d22
RR
829 // If there is no m_mainWidget between m_widget and m_wxwindow there
830 // is no need to set the size or position of m_wxwindow.
7d9f12f3
VS
831 }
832
833 m_sizeSet = TRUE;
834
835 // send size event to frame
836 wxSizeEvent event( wxSize(m_width,m_height), GetId() );
837 event.SetEventObject( this );
838 GetEventHandler()->ProcessEvent( event );
839
840 m_resizing = FALSE;
841}
842
843void wxTopLevelWindowGTK::OnInternalIdle()
844{
845 if (!m_sizeSet && GTK_WIDGET_REALIZED(m_wxwindow))
846 {
847 GtkOnSize( m_x, m_y, m_width, m_height );
848
849 // we'll come back later
850 if (g_isIdle)
851 wxapp_install_idle_handler();
852 return;
853 }
854
6aeb6f2a
VZ
855 // set the focus if not done yet and if we can already do it
856 if ( GTK_WIDGET_REALIZED(m_wxwindow) )
857 {
cc06fe74
MB
858 if ( g_delayedFocus &&
859 wxGetTopLevelParent((wxWindow*)g_delayedFocus) == this )
6aeb6f2a 860 {
2b5f62a0
VZ
861 wxLogTrace(_T("focus"),
862 _T("Setting focus from wxTLW::OnIdle() to %s(%s)"),
863 g_delayedFocus->GetClassInfo()->GetClassName(),
864 g_delayedFocus->GetLabel().c_str());
865
6aeb6f2a
VZ
866 g_delayedFocus->SetFocus();
867 g_delayedFocus = NULL;
868 }
869 }
870
7d9f12f3
VS
871 wxWindow::OnInternalIdle();
872}
873
7d9f12f3
VS
874// ----------------------------------------------------------------------------
875// frame title/icon
876// ----------------------------------------------------------------------------
877
878void wxTopLevelWindowGTK::SetTitle( const wxString &title )
879{
82b978d7
RD
880 wxASSERT_MSG( (m_widget != NULL), wxT("invalid frame") );
881
7d9f12f3 882 m_title = title;
fab591c5 883 gtk_window_set_title( GTK_WINDOW(m_widget), wxGTK_CONV( title ) );
7d9f12f3
VS
884}
885
f618020a 886void wxTopLevelWindowGTK::DoSetIcon( const wxIcon &icon )
7d9f12f3 887{
f618020a 888 if ( !icon.Ok() )
7d9f12f3
VS
889 return;
890
891 if (!m_widget->window)
892 return;
893
894 wxMask *mask = icon.GetMask();
895 GdkBitmap *bm = (GdkBitmap *) NULL;
896 if (mask) bm = mask->GetBitmap();
897
898 gdk_window_set_icon( m_widget->window, (GdkWindow *) NULL, icon.GetPixmap(), bm );
899}
900
f618020a
MB
901void wxTopLevelWindowGTK::SetIcon( const wxIcon &icon )
902{
903 SetIcons( wxIconBundle( icon ) );
904}
905
906void wxTopLevelWindowGTK::SetIcons( const wxIconBundle &icons )
907{
82b978d7 908 wxASSERT_MSG( (m_widget != NULL), wxT("invalid frame") );
f618020a 909 GdkWindow* window = m_widget->window;
f618020a
MB
910
911 wxTopLevelWindowBase::SetIcons( icons );
912
913 DoSetIcon( icons.GetIcon( -1 ) );
52d6235d
VZ
914 if ( window )
915 {
7efaed4d
MB
916 wxSetIconsX11( (WXDisplay*)GDK_WINDOW_XDISPLAY( window ),
917 (WXWindow)GDK_WINDOW_XWINDOW( window ), icons );
52d6235d 918 }
f618020a
MB
919}
920
7d9f12f3
VS
921// ----------------------------------------------------------------------------
922// frame state: maximized/iconized/normal
923// ----------------------------------------------------------------------------
924
8805e155 925void wxTopLevelWindowGTK::Maximize(bool maximize)
7d9f12f3 926{
8805e155
RR
927#ifdef __WXGTK20__
928 if (maximize)
929 gtk_window_maximize( GTK_WINDOW( m_widget ) );
930 else
931 gtk_window_unmaximize( GTK_WINDOW( m_widget ) );
932#else
7d9f12f3 933 wxFAIL_MSG( _T("not implemented") );
8805e155 934#endif
7d9f12f3
VS
935}
936
937bool wxTopLevelWindowGTK::IsMaximized() const
938{
d8e1fe80
VS
939#ifdef __WXGTK20__
940 if(!m_widget->window)
941 return false;
942
943 return gdk_window_get_state(m_widget->window) & GDK_WINDOW_STATE_MAXIMIZED;
944#else
7d9f12f3
VS
945 // wxFAIL_MSG( _T("not implemented") );
946
947 // This is an approximation
948 return FALSE;
d8e1fe80 949#endif
7d9f12f3
VS
950}
951
952void wxTopLevelWindowGTK::Restore()
953{
387fd89d 954#ifdef __WXGTK20__
8805e155
RR
955 // "Present" seems similar enough to "restore"
956 gtk_window_present( GTK_WINDOW( m_widget ) );
957#else
7d9f12f3 958 wxFAIL_MSG( _T("not implemented") );
8805e155 959#endif
7d9f12f3
VS
960}
961
962void wxTopLevelWindowGTK::Iconize( bool iconize )
963{
8805e155
RR
964#ifdef __WXGTK20__
965 if (iconize)
966 gtk_window_iconify( GTK_WINDOW( m_widget ) );
967 else
968 gtk_window_deiconify( GTK_WINDOW( m_widget ) );
969#else
7d9f12f3
VS
970 if (iconize)
971 {
972 GdkWindow *window = m_widget->window;
973
974 // you should do it later, for example from OnCreate() handler
975 wxCHECK_RET( window, _T("frame not created yet - can't iconize") );
976
977 XIconifyWindow( GDK_WINDOW_XDISPLAY( window ),
978 GDK_WINDOW_XWINDOW( window ),
979 DefaultScreen( GDK_DISPLAY() ) );
980 }
8805e155 981#endif
7d9f12f3
VS
982}
983
984bool wxTopLevelWindowGTK::IsIconized() const
985{
986 return m_isIconized;
987}
988
989void wxTopLevelWindowGTK::SetIconizeState(bool iconize)
990{
991 if ( iconize != m_isIconized )
992 {
993 m_isIconized = iconize;
994 (void)SendIconizeEvent(iconize);
995 }
996}
997
5152b0e5
JS
998void wxTopLevelWindowGTK::AddGrab()
999{
1000 if (!m_grabbed)
1001 {
1002 m_grabbed = TRUE;
1003 gtk_grab_add( m_widget );
1004 gtk_main();
1005 gtk_grab_remove( m_widget );
1006 }
1007}
1008
1009void wxTopLevelWindowGTK::RemoveGrab()
1010{
1011 if (m_grabbed)
1012 {
1013 gtk_main_quit();
1014 m_grabbed = FALSE;
1015 }
1016}
801225c1 1017
1542ea39
RD
1018
1019// helper
1020static bool do_shape_combine_region(GdkWindow* window, const wxRegion& region)
1021{
1022 if (window)
1023 {
1024 if (region.IsEmpty())
1025 {
1026 gdk_window_shape_combine_mask(window, NULL, 0, 0);
1027 }
1028 else
1029 {
1030#ifdef __WXGTK20__
1031 gdk_window_shape_combine_region(window, region.GetRegion(), 0, 0);
1032#else
1033 wxBitmap bmp = region.ConvertToBitmap();
819451b6 1034 bmp.SetMask(new wxMask(bmp, *wxBLACK));
1542ea39
RD
1035 GdkBitmap* mask = bmp.GetMask()->GetBitmap();
1036 gdk_window_shape_combine_mask(window, mask, 0, 0);
1037#endif
1038 return TRUE;
1039 }
1040 }
1041 return FALSE;
1042}
1043
1044
1045bool wxTopLevelWindowGTK::SetShape(const wxRegion& region)
1046{
6a7e6411
RD
1047 wxCHECK_MSG( HasFlag(wxFRAME_SHAPED), FALSE,
1048 _T("Shaped windows must be created with the wxFRAME_SHAPED style."));
1049
1542ea39
RD
1050 GdkWindow *window = NULL;
1051 if (m_wxwindow)
1052 {
1053 window = GTK_PIZZA(m_wxwindow)->bin_window;
1054 do_shape_combine_region(window, region);
1055 }
1056 window = m_widget->window;
1057 return do_shape_combine_region(window, region);
1058}
1059
801225c1 1060// vi:sts=4:sw=4:et