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