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