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