]> git.saurik.com Git - wxWidgets.git/blame - src/gtk1/toplevel.cpp
Unicode build fix
[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
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
e1bf3ad3 31#include "wx/toplevel.h"
2b5f62a0 32#include "wx/log.h"
7d9f12f3
VS
33#include "wx/dialog.h"
34#include "wx/control.h"
35#include "wx/app.h"
36#include "wx/dcclient.h"
fab591c5 37#include "wx/gtk/private.h"
8166ab43 38#include "wx/timer.h"
ca06ee0d 39#include "wx/settings.h"
924b84ab 40#include "wx/evtloop.h"
7d9f12f3
VS
41
42#include <glib.h>
43#include <gdk/gdk.h>
44#include <gtk/gtk.h>
45#include <gdk/gdkkeysyms.h>
46#include <gdk/gdkx.h>
47
48#include "wx/gtk/win_gtk.h"
49
f618020a
MB
50#include "wx/unix/utilsx11.h"
51
8a9650ea
RR
52// XA_CARDINAL
53#include <X11/Xatom.h>
54
7d9f12f3
VS
55// ----------------------------------------------------------------------------
56// idle system
57// ----------------------------------------------------------------------------
58
59extern void wxapp_install_idle_handler();
60extern bool g_isIdle;
7d9f12f3 61
7d9f12f3
VS
62// ----------------------------------------------------------------------------
63// data
64// ----------------------------------------------------------------------------
65
06fda9e8 66extern wxList wxPendingDelete;
d7fa7eaa 67
06fda9e8
RR
68extern int g_openDialogs;
69extern wxWindowGTK *g_delayedFocus;
70
71// the frame that is currently active (i.e. its child has focus). It is
72// used to generate wxActivateEvents
73static wxTopLevelWindowGTK *g_activeFrame = (wxTopLevelWindowGTK*) NULL;
74static wxTopLevelWindowGTK *g_lastActiveFrame = (wxTopLevelWindowGTK*) NULL;
75
76// if we detect that the app has got/lost the focus, we set this variable to
77// either TRUE or FALSE and an activate event will be sent during the next
78// OnIdle() call and it is reset to -1: this value means that we shouldn't
79// send any activate events at all
0a164d4c 80static int g_sendActivateEvent = -1;
06fda9e8 81
dca92ddf
MR
82//-----------------------------------------------------------------------------
83// RequestUserAttention related functions
84//-----------------------------------------------------------------------------
85
86extern "C" {
87static void wxgtk_window_set_urgency_hint (GtkWindow *win,
88 gboolean setting)
89{
90 wxASSERT_MSG( GTK_WIDGET_REALIZED(win), wxT("wxgtk_window_set_urgency_hint: GdkWindow not realized") );
91 GdkWindow *window = GTK_WIDGET(win)->window;
92 XWMHints *wm_hints;
93
94 wm_hints = XGetWMHints(GDK_WINDOW_XDISPLAY(window), GDK_WINDOW_XWINDOW(window));
95
96 if (!wm_hints)
97 wm_hints = XAllocWMHints();
98
99 if (setting)
100 wm_hints->flags |= XUrgencyHint;
101 else
102 wm_hints->flags &= ~XUrgencyHint;
103
104 XSetWMHints(GDK_WINDOW_XDISPLAY(window), GDK_WINDOW_XWINDOW(window), wm_hints);
105 XFree(wm_hints);
106}
107
ef1a9be4 108static gint gtk_frame_urgency_timer_callback( wxTopLevelWindowGTK *win )
dca92ddf 109{
6925aa36 110#if defined(__WXGTK20__) && GTK_CHECK_VERSION(2,7,0)
dca92ddf 111 if(!gtk_check_version(2,7,0))
ef1a9be4 112 gtk_window_set_urgency_hint(GTK_WINDOW( win->m_widget ), FALSE);
dca92ddf
MR
113 else
114#endif
ef1a9be4 115 wxgtk_window_set_urgency_hint(GTK_WINDOW( win->m_widget ), FALSE);
dca92ddf 116
ef1a9be4 117 win->m_urgency_hint = -2;
dca92ddf
MR
118 return FALSE;
119}
120}
121
06fda9e8
RR
122//-----------------------------------------------------------------------------
123// "focus_in_event"
124//-----------------------------------------------------------------------------
125
865bb325 126extern "C" {
06fda9e8
RR
127static gint gtk_frame_focus_in_callback( GtkWidget *widget,
128 GdkEvent *WXUNUSED(event),
129 wxTopLevelWindowGTK *win )
130{
131 if (g_isIdle)
132 wxapp_install_idle_handler();
0a164d4c 133
06fda9e8
RR
134 switch ( g_sendActivateEvent )
135 {
136 case -1:
137 // we've got focus from outside, synthetize wxActivateEvent
138 g_sendActivateEvent = 1;
139 break;
140
141 case 0:
142 // another our window just lost focus, it was already ours before
143 // - don't send any wxActivateEvent
144 g_sendActivateEvent = -1;
145 break;
146 }
147
148 g_activeFrame = win;
149 g_lastActiveFrame = g_activeFrame;
0a164d4c 150
06fda9e8 151 // wxPrintf( wxT("active: %s\n"), win->GetTitle().c_str() );
0a164d4c 152
dca92ddf 153 // MR: wxRequestUserAttention related block
ef1a9be4 154 switch( win->m_urgency_hint )
dca92ddf
MR
155 {
156 default:
ef1a9be4 157 gtk_timeout_remove( win->m_urgency_hint );
dca92ddf
MR
158 // no break, fallthrough to remove hint too
159 case -1:
6925aa36 160#if defined(__WXGTK20__) && GTK_CHECK_VERSION(2,7,0)
dca92ddf
MR
161 if(!gtk_check_version(2,7,0))
162 gtk_window_set_urgency_hint(GTK_WINDOW( widget ), FALSE);
163 else
164#endif
165 {
166 wxgtk_window_set_urgency_hint(GTK_WINDOW( widget ), FALSE);
167 }
168
ef1a9be4 169 win->m_urgency_hint = -2;
dca92ddf
MR
170 break;
171
172 case -2: break;
173 }
174
06fda9e8 175 wxLogTrace(wxT("activate"), wxT("Activating frame %p (from focus_in)"), g_activeFrame);
0a164d4c 176 wxActivateEvent event(wxEVT_ACTIVATE, true, g_activeFrame->GetId());
06fda9e8
RR
177 event.SetEventObject(g_activeFrame);
178 g_activeFrame->GetEventHandler()->ProcessEvent(event);
179
576f7127 180 return FALSE;
06fda9e8 181}
865bb325 182}
06fda9e8
RR
183
184//-----------------------------------------------------------------------------
185// "focus_out_event"
186//-----------------------------------------------------------------------------
187
865bb325 188extern "C" {
0a164d4c
WS
189static gint gtk_frame_focus_out_callback( GtkWidget *widget,
190 GdkEventFocus *WXUNUSED(gdk_event),
06fda9e8
RR
191 wxTopLevelWindowGTK *win )
192{
193 if (g_isIdle)
194 wxapp_install_idle_handler();
195
196 // if the focus goes out of our app alltogether, OnIdle() will send
197 // wxActivateEvent, otherwise gtk_window_focus_in_callback() will reset
198 // g_sendActivateEvent to -1
199 g_sendActivateEvent = 0;
0a164d4c 200
06fda9e8 201 // wxASSERT_MSG( (g_activeFrame == win), wxT("TLW deactivatd although it wasn't active") );
0a164d4c 202
06fda9e8 203 // wxPrintf( wxT("inactive: %s\n"), win->GetTitle().c_str() );
06fda9e8 204
cc0c05cd
JS
205 if (g_activeFrame)
206 {
207 wxLogTrace(wxT("activate"), wxT("Activating frame %p (from focus_in)"), g_activeFrame);
0a164d4c 208 wxActivateEvent event(wxEVT_ACTIVATE, false, g_activeFrame->GetId());
cc0c05cd
JS
209 event.SetEventObject(g_activeFrame);
210 g_activeFrame->GetEventHandler()->ProcessEvent(event);
211
212 g_activeFrame = NULL;
213 }
0a164d4c 214
576f7127 215 return FALSE;
06fda9e8 216}
865bb325 217}
7d9f12f3 218
7d9f12f3
VS
219//-----------------------------------------------------------------------------
220// "focus" from m_window
221//-----------------------------------------------------------------------------
222
865bb325 223extern "C" {
7d9f12f3
VS
224static gint gtk_frame_focus_callback( GtkWidget *widget, GtkDirectionType WXUNUSED(d), wxWindow *WXUNUSED(win) )
225{
226 if (g_isIdle)
227 wxapp_install_idle_handler();
228
229 // This disables GTK's tab traversal
230 gtk_signal_emit_stop_by_name( GTK_OBJECT(widget), "focus" );
231 return TRUE;
232}
865bb325 233}
7d9f12f3
VS
234
235//-----------------------------------------------------------------------------
236// "size_allocate"
237//-----------------------------------------------------------------------------
238
865bb325 239extern "C" {
7d9f12f3
VS
240static void gtk_frame_size_callback( GtkWidget *WXUNUSED(widget), GtkAllocation* alloc, wxTopLevelWindowGTK *win )
241{
242 if (g_isIdle)
243 wxapp_install_idle_handler();
244
245 if (!win->m_hasVMT)
246 return;
247
248 if ((win->m_width != alloc->width) || (win->m_height != alloc->height))
249 {
250/*
251 wxPrintf( "OnSize from " );
252 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
253 wxPrintf( win->GetClassInfo()->GetClassName() );
254 wxPrintf( " %d %d %d %d\n", (int)alloc->x,
255 (int)alloc->y,
256 (int)alloc->width,
257 (int)alloc->height );
258*/
259
260 win->m_width = alloc->width;
261 win->m_height = alloc->height;
7d9f12f3
VS
262 win->GtkUpdateSize();
263 }
264}
865bb325 265}
7d9f12f3
VS
266
267//-----------------------------------------------------------------------------
268// "delete_event"
269//-----------------------------------------------------------------------------
270
865bb325 271extern "C" {
7d9f12f3
VS
272static gint gtk_frame_delete_callback( GtkWidget *WXUNUSED(widget), GdkEvent *WXUNUSED(event), wxTopLevelWindowGTK *win )
273{
274 if (g_isIdle)
275 wxapp_install_idle_handler();
276
277 if (win->IsEnabled() &&
5152b0e5
JS
278 (g_openDialogs == 0 || (win->GetExtraStyle() & wxTOPLEVEL_EX_DIALOG) ||
279 win->IsGrabbed()))
7d9f12f3
VS
280 win->Close();
281
282 return TRUE;
283}
865bb325 284}
7d9f12f3
VS
285
286
287//-----------------------------------------------------------------------------
288// "configure_event"
289//-----------------------------------------------------------------------------
290
865bb325 291extern "C" {
7d9f12f3 292static gint
7d9f12f3 293gtk_frame_configure_callback( GtkWidget *WXUNUSED(widget), GdkEventConfigure *WXUNUSED(event), wxTopLevelWindowGTK *win )
7d9f12f3
VS
294{
295 if (g_isIdle)
296 wxapp_install_idle_handler();
297
48f72114 298 if (!win->m_hasVMT || !win->IsShown())
7d9f12f3
VS
299 return FALSE;
300
32f2ebbf 301
7d9f12f3
VS
302 int x = 0;
303 int y = 0;
304 gdk_window_get_root_origin( win->m_widget->window, &x, &y );
305 win->m_x = x;
306 win->m_y = y;
7d9f12f3
VS
307
308 wxMoveEvent mevent( wxPoint(win->m_x,win->m_y), win->GetId() );
309 mevent.SetEventObject( win );
310 win->GetEventHandler()->ProcessEvent( mevent );
311
312 return FALSE;
313}
865bb325 314}
7d9f12f3
VS
315
316//-----------------------------------------------------------------------------
317// "realize" from m_widget
318//-----------------------------------------------------------------------------
319
e1f14d22
RR
320// we cannot MWM hints and icons before the widget has been realized,
321// so we do this directly after realization
7d9f12f3 322
865bb325 323extern "C" {
7d9f12f3 324static void
6aeb6f2a
VZ
325gtk_frame_realized_callback( GtkWidget * WXUNUSED(widget),
326 wxTopLevelWindowGTK *win )
7d9f12f3
VS
327{
328 if (g_isIdle)
329 wxapp_install_idle_handler();
330
e1f14d22
RR
331 // All this is for Motif Window Manager "hints" and is supposed to be
332 // recognized by other WM as well. Not tested.
82c9f85c 333 gdk_window_set_decorations(win->m_widget->window,
f819b4a3 334 (GdkWMDecoration)win->m_gdkDecor);
82c9f85c 335 gdk_window_set_functions(win->m_widget->window,
f819b4a3 336 (GdkWMFunction)win->m_gdkFunc);
7d9f12f3 337
e1f14d22 338 // GTK's shrinking/growing policy
f819b4a3 339 if ((win->m_gdkFunc & GDK_FUNC_RESIZE) == 0)
7d9f12f3
VS
340 gtk_window_set_policy(GTK_WINDOW(win->m_widget), 0, 0, 1);
341 else
342 gtk_window_set_policy(GTK_WINDOW(win->m_widget), 1, 1, 1);
343
e1f14d22 344 // reset the icon
7efaed4d 345 wxIconBundle iconsOld = win->GetIcons();
6aeb6f2a 346 if ( iconsOld.GetIcon(-1).Ok() )
7d9f12f3 347 {
7d9f12f3 348 win->SetIcon( wxNullIcon );
7efaed4d 349 win->SetIcons( iconsOld );
7d9f12f3 350 }
7d9f12f3 351}
865bb325 352}
7d9f12f3
VS
353
354//-----------------------------------------------------------------------------
355// "map_event" from m_widget
356//-----------------------------------------------------------------------------
357
865bb325 358extern "C" {
7d9f12f3
VS
359static void
360gtk_frame_map_callback( GtkWidget * WXUNUSED(widget),
361 GdkEvent * WXUNUSED(event),
362 wxTopLevelWindow *win )
363{
0a164d4c 364 win->SetIconizeState(false);
7d9f12f3 365}
865bb325 366}
7d9f12f3
VS
367
368//-----------------------------------------------------------------------------
369// "unmap_event" from m_widget
370//-----------------------------------------------------------------------------
371
865bb325 372extern "C" {
7d9f12f3
VS
373static void
374gtk_frame_unmap_callback( GtkWidget * WXUNUSED(widget),
375 GdkEvent * WXUNUSED(event),
376 wxTopLevelWindow *win )
377{
378 win->SetIconizeState(TRUE);
379}
865bb325 380}
7d9f12f3
VS
381
382//-----------------------------------------------------------------------------
383// "expose_event" of m_client
384//-----------------------------------------------------------------------------
385
865bb325 386extern "C" {
7d9f12f3
VS
387static int gtk_window_expose_callback( GtkWidget *widget, GdkEventExpose *gdk_event, wxWindow *win )
388{
389 GtkPizza *pizza = GTK_PIZZA(widget);
390
90350682
VZ
391 gtk_paint_flat_box (win->m_widget->style,
392 pizza->bin_window, GTK_STATE_NORMAL,
393 GTK_SHADOW_NONE,
394 &gdk_event->area,
395 win->m_widget,
396 (char *)"base",
397 0, 0, -1, -1);
7d9f12f3 398
cba9ef7f 399 return FALSE;
7d9f12f3 400}
865bb325 401}
7d9f12f3
VS
402
403//-----------------------------------------------------------------------------
404// "draw" of m_client
405//-----------------------------------------------------------------------------
406
52d6235d 407#ifndef __WXGTK20__
7d9f12f3 408
865bb325 409extern "C" {
7d9f12f3
VS
410static void gtk_window_draw_callback( GtkWidget *widget, GdkRectangle *rect, wxWindow *win )
411{
412 GtkPizza *pizza = GTK_PIZZA(widget);
413
90350682
VZ
414 gtk_paint_flat_box (win->m_widget->style,
415 pizza->bin_window, GTK_STATE_NORMAL,
416 GTK_SHADOW_NONE,
417 rect,
418 win->m_widget,
419 (char *)"base",
420 0, 0, -1, -1);
7d9f12f3 421}
865bb325 422}
7d9f12f3 423
52d6235d
VZ
424#endif // GTK+ 1.x
425
7d9f12f3
VS
426// ----------------------------------------------------------------------------
427// wxTopLevelWindowGTK itself
428// ----------------------------------------------------------------------------
429
430//-----------------------------------------------------------------------------
431// InsertChild for wxTopLevelWindowGTK
432//-----------------------------------------------------------------------------
433
434/* Callback for wxTopLevelWindowGTK. This very strange beast has to be used because
435 * C++ has no virtual methods in a constructor. We have to emulate a
77ffb593 436 * virtual function here as wxWidgets requires different ways to insert
7d9f12f3
VS
437 * a child in container classes. */
438
439static void wxInsertChildInTopLevelWindow( wxTopLevelWindowGTK* parent, wxWindow* child )
440{
441 wxASSERT( GTK_IS_WIDGET(child->m_widget) );
442
443 if (!parent->m_insertInClientArea)
444 {
e1f14d22 445 // these are outside the client area
7d9f12f3
VS
446 wxTopLevelWindowGTK* frame = (wxTopLevelWindowGTK*) parent;
447 gtk_pizza_put( GTK_PIZZA(frame->m_mainWidget),
448 GTK_WIDGET(child->m_widget),
449 child->m_x,
450 child->m_y,
451 child->m_width,
452 child->m_height );
453 }
454 else
455 {
e1f14d22 456 // these are inside the client area
7d9f12f3
VS
457 gtk_pizza_put( GTK_PIZZA(parent->m_wxwindow),
458 GTK_WIDGET(child->m_widget),
e4b7b2b0
VS
459 child->m_x,
460 child->m_y,
7d9f12f3
VS
461 child->m_width,
462 child->m_height );
463 }
464
e1f14d22 465 // resize on OnInternalIdle
7d9f12f3
VS
466 parent->GtkUpdateSize();
467}
468
469// ----------------------------------------------------------------------------
470// wxTopLevelWindowGTK creation
471// ----------------------------------------------------------------------------
472
473void wxTopLevelWindowGTK::Init()
474{
0a164d4c 475 m_sizeSet = false;
7d9f12f3
VS
476 m_miniEdge = 0;
477 m_miniTitle = 0;
478 m_mainWidget = (GtkWidget*) NULL;
0a164d4c
WS
479 m_insertInClientArea = true;
480 m_isIconized = false;
481 m_fsIsShowing = false;
482 m_themeEnabled = true;
f819b4a3 483 m_gdkDecor = m_gdkFunc = 0;
0a164d4c 484 m_grabbed = false;
dca92ddf 485
ef1a9be4 486 m_urgency_hint = -2;
7d9f12f3
VS
487}
488
489bool wxTopLevelWindowGTK::Create( wxWindow *parent,
f819b4a3
VS
490 wxWindowID id,
491 const wxString& title,
492 const wxPoint& pos,
493 const wxSize& sizeOrig,
494 long style,
495 const wxString &name )
7d9f12f3
VS
496{
497 // always create a frame of some reasonable, even if arbitrary, size (at
498 // least for MSW compatibility)
499 wxSize size = sizeOrig;
1111cedc 500 size.x = WidthDefault(size.x);
66202a7e 501 size.y = HeightDefault(size.y);
7d9f12f3
VS
502
503 wxTopLevelWindows.Append( this );
504
0a164d4c 505 m_needParent = false;
6aeb6f2a 506
7d9f12f3
VS
507 if (!PreCreation( parent, pos, size ) ||
508 !CreateBase( parent, id, pos, size, style, wxDefaultValidator, name ))
509 {
510 wxFAIL_MSG( wxT("wxTopLevelWindowGTK creation failed") );
0a164d4c 511 return false;
7d9f12f3
VS
512 }
513
514 m_title = title;
515
516 m_insertCallback = (wxInsertChildFunction) wxInsertChildInTopLevelWindow;
517
63c5efa3
VS
518 // NB: m_widget may be !=NULL if it was created by derived class' Create,
519 // e.g. in wxTaskBarIconAreaGTK
520 if (m_widget == NULL)
521 {
63c5efa3
VS
522 if (GetExtraStyle() & wxTOPLEVEL_EX_DIALOG)
523 {
9e691f46 524#ifdef __WXGTK20__
4d8d6490
VS
525 m_widget = gtk_window_new(GTK_WINDOW_TOPLEVEL);
526 // Tell WM that this is a dialog window and make it center
527 // on parent by default (this is what GtkDialog ctor does):
528 gtk_window_set_type_hint(GTK_WINDOW(m_widget),
529 GDK_WINDOW_TYPE_HINT_DIALOG);
530 gtk_window_set_position(GTK_WINDOW(m_widget),
531 GTK_WIN_POS_CENTER_ON_PARENT);
9e691f46 532#else
4d8d6490 533 m_widget = gtk_window_new(GTK_WINDOW_DIALOG);
9e691f46 534#endif
63c5efa3 535 }
4d8d6490
VS
536 else
537 {
37780c64 538 m_widget = gtk_window_new(GTK_WINDOW_TOPLEVEL);
606ce80c 539#if GTK_CHECK_VERSION(2,1,0)
caf3e97f 540 if (!gtk_check_version(2,1,0))
11475235 541 {
caf3e97f
KH
542 if (style & wxFRAME_TOOL_WINDOW)
543 {
544 gtk_window_set_type_hint(GTK_WINDOW(m_widget),
545 GDK_WINDOW_TYPE_HINT_UTILITY);
0a164d4c 546
caf3e97f
KH
547 // On some WMs, like KDE, a TOOL_WINDOW will still show
548 // on the taskbar, but on Gnome a TOOL_WINDOW will not.
0a164d4c 549 // For consistency between WMs and with Windows, we
caf3e97f
KH
550 // should set the NO_TASKBAR flag which will apply
551 // the set_skip_taskbar_hint if it is available,
552 // ensuring no taskbar entry will appear.
553 style |= wxFRAME_NO_TASKBAR;
554 }
11475235 555 }
cf49c955 556#endif
4d8d6490 557 }
63c5efa3 558 }
7d9f12f3 559
e25c7537
VS
560 wxWindow *topParent = wxGetTopLevelParent(m_parent);
561 if (topParent && (((GTK_IS_WINDOW(topParent->m_widget)) &&
0a164d4c
WS
562 (GetExtraStyle() & wxTOPLEVEL_EX_DIALOG)) ||
563 (style & wxFRAME_FLOAT_ON_PARENT)))
7cd95599 564 {
e25c7537
VS
565 gtk_window_set_transient_for( GTK_WINDOW(m_widget),
566 GTK_WINDOW(topParent->m_widget) );
7cd95599 567 }
7d9f12f3 568
2be125e6 569#if GTK_CHECK_VERSION(2,2,0)
caf3e97f 570 if (!gtk_check_version(2,2,0))
2be125e6 571 {
caf3e97f
KH
572 if (style & wxFRAME_NO_TASKBAR)
573 {
574 gtk_window_set_skip_taskbar_hint(GTK_WINDOW(m_widget), TRUE);
575 }
2be125e6
VS
576 }
577#endif
578
2fca39c9 579#if GTK_CHECK_VERSION(2,4,0)
81a3313a 580 if (!gtk_check_version(2,4,0))
2fca39c9 581 {
81a3313a
RR
582 if (style & wxSTAY_ON_TOP)
583 {
584 gtk_window_set_keep_above(GTK_WINDOW(m_widget), TRUE);
585 }
2fca39c9
KH
586 }
587#endif
588
0a164d4c 589 if (!name.empty())
fab591c5 590 gtk_window_set_wmclass( GTK_WINDOW(m_widget), wxGTK_CONV( name ), wxGTK_CONV( name ) );
7d9f12f3 591
fab591c5 592 gtk_window_set_title( GTK_WINDOW(m_widget), wxGTK_CONV( title ) );
7d9f12f3
VS
593 GTK_WIDGET_UNSET_FLAGS( m_widget, GTK_CAN_FOCUS );
594
595 gtk_signal_connect( GTK_OBJECT(m_widget), "delete_event",
596 GTK_SIGNAL_FUNC(gtk_frame_delete_callback), (gpointer)this );
597
e1f14d22 598 // m_mainWidget holds the toolbar, the menubar and the client area
7d9f12f3
VS
599 m_mainWidget = gtk_pizza_new();
600 gtk_widget_show( m_mainWidget );
601 GTK_WIDGET_UNSET_FLAGS( m_mainWidget, GTK_CAN_FOCUS );
602 gtk_container_add( GTK_CONTAINER(m_widget), m_mainWidget );
603
cba9ef7f
RR
604 if (m_miniEdge == 0) // wxMiniFrame has its own version.
605 {
606 // For m_mainWidget themes
607 gtk_signal_connect( GTK_OBJECT(m_mainWidget), "expose_event",
7d9f12f3 608 GTK_SIGNAL_FUNC(gtk_window_expose_callback), (gpointer)this );
4e5a4c69 609#ifndef __WXGTK20__
cba9ef7f 610 gtk_signal_connect( GTK_OBJECT(m_mainWidget), "draw",
7d9f12f3 611 GTK_SIGNAL_FUNC(gtk_window_draw_callback), (gpointer)this );
4e5a4c69 612#endif
cba9ef7f 613 }
7d9f12f3 614
e1f14d22 615 // m_wxwindow only represents the client area without toolbar and menubar
7d9f12f3
VS
616 m_wxwindow = gtk_pizza_new();
617 gtk_widget_show( m_wxwindow );
618 gtk_container_add( GTK_CONTAINER(m_mainWidget), m_wxwindow );
619
e1f14d22
RR
620 // we donm't allow the frame to get the focus as otherwise
621 // the frame will grab it at arbitrary focus changes
7d9f12f3
VS
622 GTK_WIDGET_UNSET_FLAGS( m_wxwindow, GTK_CAN_FOCUS );
623
624 if (m_parent) m_parent->AddChild( this );
625
e1f14d22 626 // the user resized the frame by dragging etc.
7d9f12f3
VS
627 gtk_signal_connect( GTK_OBJECT(m_widget), "size_allocate",
628 GTK_SIGNAL_FUNC(gtk_frame_size_callback), (gpointer)this );
629
630 PostCreation();
631
632 if ((m_x != -1) || (m_y != -1))
633 gtk_widget_set_uposition( m_widget, m_x, m_y );
6aeb6f2a 634
e1f14d22 635 gtk_window_set_default_size( GTK_WINDOW(m_widget), m_width, m_height );
7d9f12f3 636
e1f14d22
RR
637 // we cannot set MWM hints and icons before the widget has
638 // been realized, so we do this directly after realization
7d9f12f3
VS
639 gtk_signal_connect( GTK_OBJECT(m_widget), "realize",
640 GTK_SIGNAL_FUNC(gtk_frame_realized_callback), (gpointer) this );
641
e1f14d22 642 // map and unmap for iconized state
7d9f12f3
VS
643 gtk_signal_connect( GTK_OBJECT(m_widget), "map_event",
644 GTK_SIGNAL_FUNC(gtk_frame_map_callback), (gpointer)this );
645 gtk_signal_connect( GTK_OBJECT(m_widget), "unmap_event",
646 GTK_SIGNAL_FUNC(gtk_frame_unmap_callback), (gpointer)this );
647
e1f14d22 648 // the only way to get the window size is to connect to this event
7d9f12f3
VS
649 gtk_signal_connect( GTK_OBJECT(m_widget), "configure_event",
650 GTK_SIGNAL_FUNC(gtk_frame_configure_callback), (gpointer)this );
651
e1f14d22 652 // disable native tab traversal
7d9f12f3
VS
653 gtk_signal_connect( GTK_OBJECT(m_widget), "focus",
654 GTK_SIGNAL_FUNC(gtk_frame_focus_callback), (gpointer)this );
655
06fda9e8
RR
656 // activation
657 gtk_signal_connect( GTK_OBJECT(m_widget), "focus_in_event",
658 GTK_SIGNAL_FUNC(gtk_frame_focus_in_callback), (gpointer)this );
659 gtk_signal_connect( GTK_OBJECT(m_widget), "focus_out_event",
660 GTK_SIGNAL_FUNC(gtk_frame_focus_out_callback), (gpointer)this );
0a164d4c 661
e1f14d22 662 // decorations
f819b4a3
VS
663 if ((m_miniEdge > 0) || (style & wxSIMPLE_BORDER) || (style & wxNO_BORDER))
664 {
665 m_gdkDecor = 0;
666 m_gdkFunc = 0;
667 }
668 else
669 {
670 m_gdkDecor = (long) GDK_DECOR_BORDER;
671 m_gdkFunc = (long) GDK_FUNC_MOVE;
82c9f85c 672
f819b4a3 673 // All this is for Motif Window Manager "hints" and is supposed to be
e1f14d22 674 // recognized by other WMs as well.
f819b4a3 675 if ((style & wxCAPTION) != 0)
c3d8ee42 676 {
f819b4a3 677 m_gdkDecor |= GDK_DECOR_TITLE;
c3d8ee42 678 }
850c6ed4 679 if ((style & wxCLOSE_BOX) != 0)
f819b4a3
VS
680 {
681 m_gdkFunc |= GDK_FUNC_CLOSE;
c3d8ee42
VS
682 }
683 if ((style & wxSYSTEM_MENU) != 0)
684 {
f819b4a3
VS
685 m_gdkDecor |= GDK_DECOR_MENU;
686 }
687 if ((style & wxMINIMIZE_BOX) != 0)
688 {
689 m_gdkFunc |= GDK_FUNC_MINIMIZE;
690 m_gdkDecor |= GDK_DECOR_MINIMIZE;
691 }
692 if ((style & wxMAXIMIZE_BOX) != 0)
693 {
694 m_gdkFunc |= GDK_FUNC_MAXIMIZE;
695 m_gdkDecor |= GDK_DECOR_MAXIMIZE;
696 }
697 if ((style & wxRESIZE_BORDER) != 0)
698 {
699 m_gdkFunc |= GDK_FUNC_RESIZE;
700 m_gdkDecor |= GDK_DECOR_RESIZEH;
701 }
702 }
703
0a164d4c 704 return true;
7d9f12f3
VS
705}
706
707wxTopLevelWindowGTK::~wxTopLevelWindowGTK()
708{
5152b0e5
JS
709 if (m_grabbed)
710 {
83afe211 711 wxASSERT_MSG( FALSE, _T("Window still grabbed"));
5152b0e5
JS
712 RemoveGrab();
713 }
1cbee0b4 714
0a164d4c 715 m_isBeingDeleted = true;
6aeb6f2a 716
710968c3
VZ
717 // it may also be GtkScrolledWindow in the case of an MDI child
718 if (GTK_IS_WINDOW(m_widget))
719 {
720 gtk_window_set_focus( GTK_WINDOW(m_widget), NULL );
721 }
0a164d4c 722
06fda9e8
RR
723 if (g_activeFrame == this)
724 g_activeFrame = NULL;
725 if (g_lastActiveFrame == this)
726 g_lastActiveFrame = NULL;
7d9f12f3
VS
727}
728
8a9650ea 729
8a9650ea 730
7d9f12f3
VS
731bool wxTopLevelWindowGTK::ShowFullScreen(bool show, long style )
732{
8a8997c3 733 if (show == m_fsIsShowing)
0a164d4c 734 return false; // return what?
7d9f12f3
VS
735
736 m_fsIsShowing = show;
0a164d4c 737
1542ea39 738 wxX11FullScreenMethod method =
8166ab43
VS
739 wxGetFullScreenMethodX11((WXDisplay*)GDK_DISPLAY(),
740 (WXWindow)GDK_ROOT_WINDOW());
1542ea39 741
feb1c9fb
VS
742#if GTK_CHECK_VERSION(2,2,0)
743 // NB: gtk_window_fullscreen() uses freedesktop.org's WMspec extensions
744 // to switch to fullscreen, which is not always available. We must
745 // check if WM supports the spec and use legacy methods if it
746 // doesn't.
cc35003a 747 if ( (method == wxX11_FS_WMSPEC) && !gtk_check_version(2,2,0) )
7d9f12f3 748 {
feb1c9fb
VS
749 if (show)
750 gtk_window_fullscreen( GTK_WINDOW( m_widget ) );
751 else
752 gtk_window_unfullscreen( GTK_WINDOW( m_widget ) );
7d9f12f3
VS
753 }
754 else
8a8997c3 755#endif // GTK+ >= 2.2.0
7d9f12f3 756 {
feb1c9fb
VS
757 GdkWindow *window = m_widget->window;
758
759 if (show)
8166ab43 760 {
feb1c9fb
VS
761 m_fsSaveFlag = style;
762 GetPosition( &m_fsSaveFrame.x, &m_fsSaveFrame.y );
763 GetSize( &m_fsSaveFrame.width, &m_fsSaveFrame.height );
764
765 int screen_width,screen_height;
766 wxDisplaySize( &screen_width, &screen_height );
767
768 gint client_x, client_y, root_x, root_y;
769 gint width, height;
770
771 if (method != wxX11_FS_WMSPEC)
772 {
773 // don't do it always, Metacity hates it
774 m_fsSaveGdkFunc = m_gdkFunc;
775 m_fsSaveGdkDecor = m_gdkDecor;
776 m_gdkFunc = m_gdkDecor = 0;
777 gdk_window_set_decorations(window, (GdkWMDecoration)0);
778 gdk_window_set_functions(window, (GdkWMFunction)0);
779 }
780
781 gdk_window_get_origin (m_widget->window, &root_x, &root_y);
782 gdk_window_get_geometry (m_widget->window, &client_x, &client_y,
783 &width, &height, NULL);
784
785 gdk_window_move_resize (m_widget->window, -client_x, -client_y,
786 screen_width + 1, screen_height + 1);
787
788 wxSetFullScreenStateX11((WXDisplay*)GDK_DISPLAY(),
789 (WXWindow)GDK_ROOT_WINDOW(),
790 (WXWindow)GDK_WINDOW_XWINDOW(window),
791 show, &m_fsSaveFrame, method);
792 }
3b2931fb 793 else // hide
feb1c9fb
VS
794 {
795 if (method != wxX11_FS_WMSPEC)
796 {
797 // don't do it always, Metacity hates it
798 m_gdkFunc = m_fsSaveGdkFunc;
799 m_gdkDecor = m_fsSaveGdkDecor;
800 gdk_window_set_decorations(window, (GdkWMDecoration)m_gdkDecor);
801 gdk_window_set_functions(window, (GdkWMFunction)m_gdkFunc);
802 }
803
804 wxSetFullScreenStateX11((WXDisplay*)GDK_DISPLAY(),
805 (WXWindow)GDK_ROOT_WINDOW(),
806 (WXWindow)GDK_WINDOW_XWINDOW(window),
807 show, &m_fsSaveFrame, method);
808
809 SetSize(m_fsSaveFrame.x, m_fsSaveFrame.y,
810 m_fsSaveFrame.width, m_fsSaveFrame.height);
8166ab43 811 }
7d9f12f3 812 }
8166ab43 813
3b2931fb
VZ
814 // documented behaviour is to show the window if it's still hidden when
815 // showing it full screen
816 if ( show && !IsShown() )
817 Show();
818
0a164d4c 819 return true;
7d9f12f3
VS
820}
821
822// ----------------------------------------------------------------------------
823// overridden wxWindow methods
824// ----------------------------------------------------------------------------
825
826bool wxTopLevelWindowGTK::Show( bool show )
827{
82b978d7 828 wxASSERT_MSG( (m_widget != NULL), wxT("invalid frame") );
7d9f12f3
VS
829
830 if (show && !m_sizeSet)
831 {
832 /* by calling GtkOnSize here, we don't have to call
833 either after showing the frame, which would entail
834 much ugly flicker or from within the size_allocate
835 handler, because GTK 1.1.X forbids that. */
836
837 GtkOnSize( m_x, m_y, m_width, m_height );
838 }
0a164d4c 839
32f2ebbf
RR
840 if (show)
841 gtk_widget_set_uposition( m_widget, m_x, m_y );
0a164d4c 842
7d9f12f3
VS
843 return wxWindow::Show( show );
844}
845
a2ac55f5
RR
846void wxTopLevelWindowGTK::Raise()
847{
848#ifdef __WXGTK20__
849 gtk_window_present( GTK_WINDOW( m_widget ) );
850#else
851 wxWindow::Raise();
852#endif
853}
854
7d9f12f3
VS
855void wxTopLevelWindowGTK::DoMoveWindow(int WXUNUSED(x), int WXUNUSED(y), int WXUNUSED(width), int WXUNUSED(height) )
856{
857 wxFAIL_MSG( wxT("DoMoveWindow called for wxTopLevelWindowGTK") );
858}
859
860void wxTopLevelWindowGTK::DoSetSize( int x, int y, int width, int height, int sizeFlags )
861{
82b978d7
RD
862 wxASSERT_MSG( (m_widget != NULL), wxT("invalid frame") );
863
e1f14d22 864 // this shouldn't happen: wxFrame, wxMDIParentFrame and wxMDIChildFrame have m_wxwindow
7d9f12f3
VS
865 wxASSERT_MSG( (m_wxwindow != NULL), wxT("invalid frame") );
866
e1f14d22 867 // avoid recursions
7d9f12f3
VS
868 if (m_resizing)
869 return;
0a164d4c 870 m_resizing = true;
7d9f12f3
VS
871
872 int old_x = m_x;
873 int old_y = m_y;
874
875 int old_width = m_width;
876 int old_height = m_height;
877
878 if ((sizeFlags & wxSIZE_ALLOW_MINUS_ONE) == 0)
879 {
880 if (x != -1) m_x = x;
881 if (y != -1) m_y = y;
7d9f12f3
VS
882 }
883 else
884 {
885 m_x = x;
886 m_y = y;
7d9f12f3 887 }
d44c23ce
RR
888 if (width != -1) m_width = width;
889 if (height != -1) m_height = height;
7d9f12f3
VS
890
891/*
892 if ((sizeFlags & wxSIZE_AUTO_WIDTH) == wxSIZE_AUTO_WIDTH)
893 {
894 if (width == -1) m_width = 80;
895 }
896
897 if ((sizeFlags & wxSIZE_AUTO_HEIGHT) == wxSIZE_AUTO_HEIGHT)
898 {
899 if (height == -1) m_height = 26;
900 }
901*/
902
e7dda1ff
VS
903 int minWidth = GetMinWidth(),
904 minHeight = GetMinHeight(),
905 maxWidth = GetMaxWidth(),
906 maxHeight = GetMaxHeight();
907
62be94e1
RR
908#ifdef __WXGPE__
909 // GPE's window manager doesn't like size hints
910 // at all, esp. when the user has to use the
911 // virtual keyboard.
912 minWidth = -1;
913 minHeight = -1;
914 maxWidth = -1;
915 maxHeight = -1;
916#endif
0a164d4c 917
e7dda1ff
VS
918 if ((minWidth != -1) && (m_width < minWidth)) m_width = minWidth;
919 if ((minHeight != -1) && (m_height < minHeight)) m_height = minHeight;
920 if ((maxWidth != -1) && (m_width > maxWidth)) m_width = maxWidth;
921 if ((maxHeight != -1) && (m_height > maxHeight)) m_height = maxHeight;
7d9f12f3
VS
922
923 if ((m_x != -1) || (m_y != -1))
924 {
925 if ((m_x != old_x) || (m_y != old_y))
926 {
927 gtk_widget_set_uposition( m_widget, m_x, m_y );
928 }
929 }
930
931 if ((m_width != old_width) || (m_height != old_height))
932 {
e1f14d22
RR
933 if (m_widget->window)
934 gdk_window_resize( m_widget->window, m_width, m_height );
935 else
936 gtk_window_set_default_size( GTK_WINDOW(m_widget), m_width, m_height );
7d9f12f3
VS
937
938 /* we set the size in GtkOnSize, i.e. mostly the actual resizing is
939 done either directly before the frame is shown or in idle time
940 so that different calls to SetSize() don't lead to flicker. */
0a164d4c 941 m_sizeSet = false;
7d9f12f3
VS
942 }
943
0a164d4c 944 m_resizing = false;
7d9f12f3
VS
945}
946
947void wxTopLevelWindowGTK::DoGetClientSize( int *width, int *height ) const
948{
82b978d7
RD
949 wxASSERT_MSG( (m_widget != NULL), wxT("invalid frame") );
950
7d9f12f3
VS
951 wxWindow::DoGetClientSize( width, height );
952 if (height)
953 {
e1f14d22 954 // mini edge
7d9f12f3
VS
955 *height -= m_miniEdge*2 + m_miniTitle;
956 }
957 if (width)
958 {
959 *width -= m_miniEdge*2;
960 }
961}
962
963void wxTopLevelWindowGTK::DoSetClientSize( int width, int height )
964{
82b978d7 965 wxASSERT_MSG( (m_widget != NULL), wxT("invalid frame") );
7d9f12f3 966
82c9f85c 967 DoSetSize(-1, -1,
7d9f12f3
VS
968 width + m_miniEdge*2, height + m_miniEdge*2 + m_miniTitle, 0);
969}
970
971void wxTopLevelWindowGTK::GtkOnSize( int WXUNUSED(x), int WXUNUSED(y),
82c9f85c 972 int width, int height )
7d9f12f3
VS
973{
974 // due to a bug in gtk, x,y are always 0
975 // m_x = x;
976 // m_y = y;
977
e1f14d22 978 // avoid recursions
7d9f12f3 979 if (m_resizing) return;
0a164d4c 980 m_resizing = true;
7d9f12f3
VS
981
982 if ( m_wxwindow == NULL ) return;
983
984 m_width = width;
985 m_height = height;
986
0d53fc34 987 /* wxMDIChildFrame derives from wxFrame but it _is_ a wxWindow as it uses
7d9f12f3 988 wxWindow::Create to create it's GTK equivalent. m_mainWidget is only
0d53fc34 989 set in wxFrame::Create so it is used to check what kind of frame we
7d9f12f3
VS
990 have here. if m_mainWidget is NULL it is a wxMDIChildFrame and so we
991 skip the part which handles m_frameMenuBar, m_frameToolBar and (most
992 importantly) m_mainWidget */
993
e7dda1ff
VS
994 int minWidth = GetMinWidth(),
995 minHeight = GetMinHeight(),
996 maxWidth = GetMaxWidth(),
997 maxHeight = GetMaxHeight();
998
62be94e1
RR
999#ifdef __WXGPE__
1000 // GPE's window manager doesn't like size hints
1001 // at all, esp. when the user has to use the
1002 // virtual keyboard.
1003 minWidth = -1;
1004 minHeight = -1;
1005 maxWidth = -1;
1006 maxHeight = -1;
1007#endif
0a164d4c 1008
e7dda1ff
VS
1009 if ((minWidth != -1) && (m_width < minWidth)) m_width = minWidth;
1010 if ((minHeight != -1) && (m_height < minHeight)) m_height = minHeight;
1011 if ((maxWidth != -1) && (m_width > maxWidth)) m_width = maxWidth;
1012 if ((maxHeight != -1) && (m_height > maxHeight)) m_height = maxHeight;
7d9f12f3
VS
1013
1014 if (m_mainWidget)
1015 {
e1f14d22 1016 // set size hints
801225c1
RL
1017 gint flag = 0; // GDK_HINT_POS;
1018 GdkGeometry geom;
1019
e7dda1ff
VS
1020 if ((minWidth != -1) || (minHeight != -1)) flag |= GDK_HINT_MIN_SIZE;
1021 if ((maxWidth != -1) || (maxHeight != -1)) flag |= GDK_HINT_MAX_SIZE;
801225c1 1022
e7dda1ff
VS
1023 geom.min_width = minWidth;
1024 geom.min_height = minHeight;
801225c1
RL
1025
1026 // Because of the way we set GDK_HINT_MAX_SIZE above, if either of
1027 // maxHeight or maxWidth is set, we must set them both, else the
1028 // remaining -1 will be taken literally.
1029
1030 // I'm certain this also happens elsewhere, and is the probable
1031 // cause of other such things as:
1032 // Gtk-WARNING **: gtk_widget_size_allocate():
1033 // attempt to allocate widget with width 65535 and height 600
1034 // but I don't have time to track them all now..
1cbee0b4 1035 //
801225c1
RL
1036 // Really we need to encapulate all this height/width business and
1037 // stop any old method from ripping at the members directly and
1038 // scattering -1's without regard for who might resolve them later.
1039
1040 geom.max_width = ( maxHeight == -1 ) ? maxWidth
1041 : ( maxWidth == -1 ) ? wxGetDisplaySize().GetWidth()
1042 : maxWidth ;
1043
1044 geom.max_height = ( maxWidth == -1 ) ? maxHeight // ( == -1 here )
1045 : ( maxHeight == -1 ) ? wxGetDisplaySize().GetHeight()
1046 : maxHeight ;
1047
7d9f12f3
VS
1048 gtk_window_set_geometry_hints( GTK_WINDOW(m_widget),
1049 (GtkWidget*) NULL,
1050 &geom,
1051 (GdkWindowHints) flag );
1052
1053 /* I revert back to wxGTK's original behaviour. m_mainWidget holds the
1054 * menubar, the toolbar and the client area, which is represented by
1055 * m_wxwindow.
1056 * this hurts in the eye, but I don't want to call SetSize()
1057 * because I don't want to call any non-native functions here. */
1058
1059 int client_x = m_miniEdge;
1060 int client_y = m_miniEdge + m_miniTitle;
1061 int client_w = m_width - 2*m_miniEdge;
1062 int client_h = m_height - 2*m_miniEdge - m_miniTitle;
801225c1 1063
7d9f12f3
VS
1064 gtk_pizza_set_size( GTK_PIZZA(m_mainWidget),
1065 m_wxwindow,
1066 client_x, client_y, client_w, client_h );
1067 }
1068 else
1069 {
e1f14d22
RR
1070 // If there is no m_mainWidget between m_widget and m_wxwindow there
1071 // is no need to set the size or position of m_wxwindow.
7d9f12f3
VS
1072 }
1073
0a164d4c 1074 m_sizeSet = true;
7d9f12f3
VS
1075
1076 // send size event to frame
1077 wxSizeEvent event( wxSize(m_width,m_height), GetId() );
1078 event.SetEventObject( this );
1079 GetEventHandler()->ProcessEvent( event );
1080
0a164d4c 1081 m_resizing = false;
7d9f12f3
VS
1082}
1083
1084void wxTopLevelWindowGTK::OnInternalIdle()
1085{
1086 if (!m_sizeSet && GTK_WIDGET_REALIZED(m_wxwindow))
1087 {
1088 GtkOnSize( m_x, m_y, m_width, m_height );
1089
1090 // we'll come back later
1091 if (g_isIdle)
1092 wxapp_install_idle_handler();
1093 return;
1094 }
1095
6aeb6f2a
VZ
1096 // set the focus if not done yet and if we can already do it
1097 if ( GTK_WIDGET_REALIZED(m_wxwindow) )
1098 {
cc06fe74
MB
1099 if ( g_delayedFocus &&
1100 wxGetTopLevelParent((wxWindow*)g_delayedFocus) == this )
6aeb6f2a 1101 {
2b5f62a0
VZ
1102 wxLogTrace(_T("focus"),
1103 _T("Setting focus from wxTLW::OnIdle() to %s(%s)"),
1104 g_delayedFocus->GetClassInfo()->GetClassName(),
1105 g_delayedFocus->GetLabel().c_str());
1106
6aeb6f2a
VZ
1107 g_delayedFocus->SetFocus();
1108 g_delayedFocus = NULL;
1109 }
1110 }
1111
7d9f12f3 1112 wxWindow::OnInternalIdle();
0a164d4c 1113
06fda9e8
RR
1114 // Synthetize activate events.
1115 if ( g_sendActivateEvent != -1 )
1116 {
1117 bool activate = g_sendActivateEvent != 0;
0a164d4c 1118
576f7127
RR
1119 // if (!activate) wxPrintf( wxT("de") );
1120 // wxPrintf( wxT("activate\n") );
0a164d4c 1121
06fda9e8
RR
1122 // do it only once
1123 g_sendActivateEvent = -1;
1124
1125 wxTheApp->SetActive(activate, (wxWindow *)g_lastActiveFrame);
1126 }
7d9f12f3
VS
1127}
1128
7d9f12f3
VS
1129// ----------------------------------------------------------------------------
1130// frame title/icon
1131// ----------------------------------------------------------------------------
1132
1133void wxTopLevelWindowGTK::SetTitle( const wxString &title )
1134{
82b978d7
RD
1135 wxASSERT_MSG( (m_widget != NULL), wxT("invalid frame") );
1136
7d9f12f3 1137 m_title = title;
fab591c5 1138 gtk_window_set_title( GTK_WINDOW(m_widget), wxGTK_CONV( title ) );
7d9f12f3
VS
1139}
1140
f618020a
MB
1141void wxTopLevelWindowGTK::SetIcon( const wxIcon &icon )
1142{
1143 SetIcons( wxIconBundle( icon ) );
1144}
1145
1146void wxTopLevelWindowGTK::SetIcons( const wxIconBundle &icons )
1147{
82b978d7 1148 wxASSERT_MSG( (m_widget != NULL), wxT("invalid frame") );
f618020a
MB
1149
1150 wxTopLevelWindowBase::SetIcons( icons );
1151
87e53e2a
VS
1152#ifdef __WXGTK20__
1153 GList *list = NULL;
1154 size_t max = icons.m_icons.GetCount();
1155
1156 for (size_t i = 0; i < max; i++)
52d6235d 1157 {
87e53e2a
VS
1158 if (icons.m_icons[i].Ok())
1159 {
1160 list = g_list_prepend(list, icons.m_icons[i].GetPixbuf());
1161 }
1162 }
1163 gtk_window_set_icon_list(GTK_WINDOW(m_widget), list);
1164 g_list_free(list);
0a164d4c 1165
87e53e2a
VS
1166#else // !__WXGTK20__
1167 GdkWindow* window = m_widget->window;
1168 if (!window)
1169 return;
1170
1171 wxIcon icon = icons.GetIcon(-1);
1172 if (icon.Ok())
1173 {
1174 wxMask *mask = icon.GetMask();
1175 GdkBitmap *bm = (GdkBitmap *) NULL;
1176 if (mask) bm = mask->GetBitmap();
1177
1178 gdk_window_set_icon( m_widget->window, (GdkWindow *) NULL, icon.GetPixmap(), bm );
52d6235d 1179 }
87e53e2a
VS
1180
1181 wxSetIconsX11( (WXDisplay*)GDK_WINDOW_XDISPLAY( window ),
1182 (WXWindow)GDK_WINDOW_XWINDOW( window ), icons );
1183#endif // !__WXGTK20__
f618020a
MB
1184}
1185
7d9f12f3
VS
1186// ----------------------------------------------------------------------------
1187// frame state: maximized/iconized/normal
1188// ----------------------------------------------------------------------------
1189
8805e155 1190void wxTopLevelWindowGTK::Maximize(bool maximize)
7d9f12f3 1191{
8805e155
RR
1192#ifdef __WXGTK20__
1193 if (maximize)
1194 gtk_window_maximize( GTK_WINDOW( m_widget ) );
1195 else
1196 gtk_window_unmaximize( GTK_WINDOW( m_widget ) );
1197#else
7d9f12f3 1198 wxFAIL_MSG( _T("not implemented") );
8805e155 1199#endif
7d9f12f3
VS
1200}
1201
1202bool wxTopLevelWindowGTK::IsMaximized() const
1203{
d8e1fe80
VS
1204#ifdef __WXGTK20__
1205 if(!m_widget->window)
1206 return false;
1207
1208 return gdk_window_get_state(m_widget->window) & GDK_WINDOW_STATE_MAXIMIZED;
1209#else
7d9f12f3
VS
1210 // wxFAIL_MSG( _T("not implemented") );
1211
1212 // This is an approximation
0a164d4c 1213 return false;
d8e1fe80 1214#endif
7d9f12f3
VS
1215}
1216
1217void wxTopLevelWindowGTK::Restore()
1218{
387fd89d 1219#ifdef __WXGTK20__
8805e155
RR
1220 // "Present" seems similar enough to "restore"
1221 gtk_window_present( GTK_WINDOW( m_widget ) );
1222#else
7d9f12f3 1223 wxFAIL_MSG( _T("not implemented") );
8805e155 1224#endif
7d9f12f3
VS
1225}
1226
1227void wxTopLevelWindowGTK::Iconize( bool iconize )
1228{
8805e155
RR
1229#ifdef __WXGTK20__
1230 if (iconize)
1231 gtk_window_iconify( GTK_WINDOW( m_widget ) );
1232 else
1233 gtk_window_deiconify( GTK_WINDOW( m_widget ) );
1234#else
7d9f12f3
VS
1235 if (iconize)
1236 {
1237 GdkWindow *window = m_widget->window;
1238
1239 // you should do it later, for example from OnCreate() handler
1240 wxCHECK_RET( window, _T("frame not created yet - can't iconize") );
1241
1242 XIconifyWindow( GDK_WINDOW_XDISPLAY( window ),
1243 GDK_WINDOW_XWINDOW( window ),
1244 DefaultScreen( GDK_DISPLAY() ) );
1245 }
8805e155 1246#endif
7d9f12f3
VS
1247}
1248
1249bool wxTopLevelWindowGTK::IsIconized() const
1250{
1251 return m_isIconized;
1252}
1253
1254void wxTopLevelWindowGTK::SetIconizeState(bool iconize)
1255{
1256 if ( iconize != m_isIconized )
1257 {
1258 m_isIconized = iconize;
1259 (void)SendIconizeEvent(iconize);
1260 }
1261}
1262
5152b0e5
JS
1263void wxTopLevelWindowGTK::AddGrab()
1264{
1265 if (!m_grabbed)
1266 {
0a164d4c 1267 m_grabbed = true;
5152b0e5 1268 gtk_grab_add( m_widget );
924b84ab 1269 wxEventLoop().Run();
5152b0e5
JS
1270 gtk_grab_remove( m_widget );
1271 }
1272}
1273
1274void wxTopLevelWindowGTK::RemoveGrab()
1275{
1276 if (m_grabbed)
1277 {
1278 gtk_main_quit();
0a164d4c 1279 m_grabbed = false;
5152b0e5
JS
1280 }
1281}
801225c1 1282
1542ea39
RD
1283
1284// helper
1285static bool do_shape_combine_region(GdkWindow* window, const wxRegion& region)
1286{
1287 if (window)
1288 {
1289 if (region.IsEmpty())
1290 {
1291 gdk_window_shape_combine_mask(window, NULL, 0, 0);
1292 }
1293 else
1294 {
1295#ifdef __WXGTK20__
0a164d4c 1296 gdk_window_shape_combine_region(window, region.GetRegion(), 0, 0);
1542ea39 1297#else
0a164d4c
WS
1298 wxBitmap bmp = region.ConvertToBitmap();
1299 bmp.SetMask(new wxMask(bmp, *wxBLACK));
1300 GdkBitmap* mask = bmp.GetMask()->GetBitmap();
1301 gdk_window_shape_combine_mask(window, mask, 0, 0);
1542ea39 1302#endif
0a164d4c 1303 return true;
1542ea39
RD
1304 }
1305 }
0a164d4c 1306 return false;
1542ea39
RD
1307}
1308
1309
1310bool wxTopLevelWindowGTK::SetShape(const wxRegion& region)
1311{
0a164d4c 1312 wxCHECK_MSG( HasFlag(wxFRAME_SHAPED), false,
6a7e6411
RD
1313 _T("Shaped windows must be created with the wxFRAME_SHAPED style."));
1314
1542ea39
RD
1315 GdkWindow *window = NULL;
1316 if (m_wxwindow)
1317 {
1318 window = GTK_PIZZA(m_wxwindow)->bin_window;
1319 do_shape_combine_region(window, region);
1320 }
1321 window = m_widget->window;
1322 return do_shape_combine_region(window, region);
1323}
1324
6b30a44e 1325bool wxTopLevelWindowGTK::IsActive()
35ff90a0 1326{
06fda9e8 1327 return (this == (wxTopLevelWindowGTK*)g_activeFrame);
35ff90a0 1328}
dca92ddf
MR
1329
1330void wxTopLevelWindowGTK::RequestUserAttention(int flags)
1331{
1332 bool new_hint_value = false;
1333
1334 // FIXME: This is a workaround to focus handling problem
1335 // If RequestUserAttention is called for example right after a wxSleep, OnInternalIdle hasn't
1336 // yet been processed, and the internal focus system is not up to date yet.
1337 // wxYieldIfNeeded ensures the processing of it, but can have unwanted side effects - MR
1338 ::wxYieldIfNeeded();
1339
dca92ddf
MR
1340 if(m_urgency_hint >= 0)
1341 gtk_timeout_remove(m_urgency_hint);
dca92ddf 1342
ef1a9be4 1343 m_urgency_hint = -2;
dca92ddf
MR
1344
1345 if( GTK_WIDGET_REALIZED(m_widget) && !IsActive() )
1346 {
1347 new_hint_value = true;
1348
1349 if (flags & wxUSER_ATTENTION_INFO)
1350 {
ef1a9be4 1351 m_urgency_hint = gtk_timeout_add(5000, (GtkFunction)gtk_frame_urgency_timer_callback, this);
dca92ddf 1352 } else {
ef1a9be4 1353 m_urgency_hint = -1;
dca92ddf
MR
1354 }
1355 }
1356
6925aa36 1357#if defined(__WXGTK20__) && GTK_CHECK_VERSION(2,7,0)
dca92ddf
MR
1358 if(!gtk_check_version(2,7,0))
1359 gtk_window_set_urgency_hint(GTK_WINDOW( m_widget ), new_hint_value);
1360 else
1361#endif
1362 wxgtk_window_set_urgency_hint(GTK_WINDOW( m_widget ), new_hint_value);
1363}