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