]> git.saurik.com Git - wxWidgets.git/blame - src/gtk/toplevel.cpp
don't try to paint hidden windows
[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 {
b2fcdf2b
RR
918 *height = m_height;
919
e1f14d22 920 // mini edge
7d9f12f3
VS
921 *height -= m_miniEdge*2 + m_miniTitle;
922 }
923 if (width)
924 {
b2fcdf2b
RR
925 *width = m_width;
926
7d9f12f3
VS
927 *width -= m_miniEdge*2;
928 }
b2fcdf2b 929
7d9f12f3
VS
930}
931
932void wxTopLevelWindowGTK::DoSetClientSize( int width, int height )
933{
82b978d7 934 wxASSERT_MSG( (m_widget != NULL), wxT("invalid frame") );
7d9f12f3 935
82c9f85c 936 DoSetSize(-1, -1,
7d9f12f3
VS
937 width + m_miniEdge*2, height + m_miniEdge*2 + m_miniTitle, 0);
938}
939
b5e31cc8 940void wxTopLevelWindowGTK::GtkOnSize()
7d9f12f3 941{
e1f14d22 942 // avoid recursions
7d9f12f3 943 if (m_resizing) return;
0a164d4c 944 m_resizing = true;
7d9f12f3
VS
945
946 if ( m_wxwindow == NULL ) return;
947
0d53fc34 948 /* wxMDIChildFrame derives from wxFrame but it _is_ a wxWindow as it uses
7d9f12f3 949 wxWindow::Create to create it's GTK equivalent. m_mainWidget is only
0d53fc34 950 set in wxFrame::Create so it is used to check what kind of frame we
7d9f12f3
VS
951 have here. if m_mainWidget is NULL it is a wxMDIChildFrame and so we
952 skip the part which handles m_frameMenuBar, m_frameToolBar and (most
953 importantly) m_mainWidget */
954
e7dda1ff
VS
955 int minWidth = GetMinWidth(),
956 minHeight = GetMinHeight(),
957 maxWidth = GetMaxWidth(),
958 maxHeight = GetMaxHeight();
959
62be94e1
RR
960#ifdef __WXGPE__
961 // GPE's window manager doesn't like size hints
962 // at all, esp. when the user has to use the
963 // virtual keyboard.
964 minWidth = -1;
965 minHeight = -1;
966 maxWidth = -1;
967 maxHeight = -1;
968#endif
0a164d4c 969
e7dda1ff
VS
970 if ((minWidth != -1) && (m_width < minWidth)) m_width = minWidth;
971 if ((minHeight != -1) && (m_height < minHeight)) m_height = minHeight;
972 if ((maxWidth != -1) && (m_width > maxWidth)) m_width = maxWidth;
973 if ((maxHeight != -1) && (m_height > maxHeight)) m_height = maxHeight;
7d9f12f3
VS
974
975 if (m_mainWidget)
976 {
e1f14d22 977 // set size hints
801225c1
RL
978 gint flag = 0; // GDK_HINT_POS;
979 GdkGeometry geom;
980
e7dda1ff
VS
981 if ((minWidth != -1) || (minHeight != -1)) flag |= GDK_HINT_MIN_SIZE;
982 if ((maxWidth != -1) || (maxHeight != -1)) flag |= GDK_HINT_MAX_SIZE;
801225c1 983
e7dda1ff
VS
984 geom.min_width = minWidth;
985 geom.min_height = minHeight;
801225c1
RL
986
987 // Because of the way we set GDK_HINT_MAX_SIZE above, if either of
988 // maxHeight or maxWidth is set, we must set them both, else the
989 // remaining -1 will be taken literally.
990
991 // I'm certain this also happens elsewhere, and is the probable
992 // cause of other such things as:
993 // Gtk-WARNING **: gtk_widget_size_allocate():
994 // attempt to allocate widget with width 65535 and height 600
995 // but I don't have time to track them all now..
1cbee0b4 996 //
801225c1
RL
997 // Really we need to encapulate all this height/width business and
998 // stop any old method from ripping at the members directly and
999 // scattering -1's without regard for who might resolve them later.
1000
1001 geom.max_width = ( maxHeight == -1 ) ? maxWidth
1002 : ( maxWidth == -1 ) ? wxGetDisplaySize().GetWidth()
1003 : maxWidth ;
1004
1005 geom.max_height = ( maxWidth == -1 ) ? maxHeight // ( == -1 here )
1006 : ( maxHeight == -1 ) ? wxGetDisplaySize().GetHeight()
1007 : maxHeight ;
1008
7d9f12f3
VS
1009 gtk_window_set_geometry_hints( GTK_WINDOW(m_widget),
1010 (GtkWidget*) NULL,
1011 &geom,
1012 (GdkWindowHints) flag );
1013
1014 /* I revert back to wxGTK's original behaviour. m_mainWidget holds the
1015 * menubar, the toolbar and the client area, which is represented by
1016 * m_wxwindow.
1017 * this hurts in the eye, but I don't want to call SetSize()
1018 * because I don't want to call any non-native functions here. */
1019
1020 int client_x = m_miniEdge;
1021 int client_y = m_miniEdge + m_miniTitle;
1022 int client_w = m_width - 2*m_miniEdge;
1023 int client_h = m_height - 2*m_miniEdge - m_miniTitle;
9cf7a6c0
PC
1024 if (client_w < 0)
1025 client_w = 0;
1026 if (client_h < 0)
1027 client_h = 0;
801225c1 1028
7d9f12f3
VS
1029 gtk_pizza_set_size( GTK_PIZZA(m_mainWidget),
1030 m_wxwindow,
1031 client_x, client_y, client_w, client_h );
1032 }
1033 else
1034 {
e1f14d22
RR
1035 // If there is no m_mainWidget between m_widget and m_wxwindow there
1036 // is no need to set the size or position of m_wxwindow.
7d9f12f3
VS
1037 }
1038
0a164d4c 1039 m_sizeSet = true;
7d9f12f3
VS
1040
1041 // send size event to frame
1042 wxSizeEvent event( wxSize(m_width,m_height), GetId() );
1043 event.SetEventObject( this );
1044 GetEventHandler()->ProcessEvent( event );
1045
0a164d4c 1046 m_resizing = false;
7d9f12f3
VS
1047}
1048
1049void wxTopLevelWindowGTK::OnInternalIdle()
1050{
1051 if (!m_sizeSet && GTK_WIDGET_REALIZED(m_wxwindow))
1052 {
b5e31cc8 1053 GtkOnSize();
7d9f12f3
VS
1054
1055 // we'll come back later
1056 if (g_isIdle)
1057 wxapp_install_idle_handler();
1058 return;
1059 }
1060
6aeb6f2a
VZ
1061 // set the focus if not done yet and if we can already do it
1062 if ( GTK_WIDGET_REALIZED(m_wxwindow) )
1063 {
cc06fe74
MB
1064 if ( g_delayedFocus &&
1065 wxGetTopLevelParent((wxWindow*)g_delayedFocus) == this )
6aeb6f2a 1066 {
2b5f62a0
VZ
1067 wxLogTrace(_T("focus"),
1068 _T("Setting focus from wxTLW::OnIdle() to %s(%s)"),
1069 g_delayedFocus->GetClassInfo()->GetClassName(),
1070 g_delayedFocus->GetLabel().c_str());
1071
6aeb6f2a
VZ
1072 g_delayedFocus->SetFocus();
1073 g_delayedFocus = NULL;
1074 }
1075 }
1076
7d9f12f3 1077 wxWindow::OnInternalIdle();
0a164d4c 1078
06fda9e8
RR
1079 // Synthetize activate events.
1080 if ( g_sendActivateEvent != -1 )
1081 {
1082 bool activate = g_sendActivateEvent != 0;
0a164d4c 1083
576f7127
RR
1084 // if (!activate) wxPrintf( wxT("de") );
1085 // wxPrintf( wxT("activate\n") );
0a164d4c 1086
06fda9e8
RR
1087 // do it only once
1088 g_sendActivateEvent = -1;
1089
1090 wxTheApp->SetActive(activate, (wxWindow *)g_lastActiveFrame);
1091 }
7d9f12f3
VS
1092}
1093
7d9f12f3
VS
1094// ----------------------------------------------------------------------------
1095// frame title/icon
1096// ----------------------------------------------------------------------------
1097
1098void wxTopLevelWindowGTK::SetTitle( const wxString &title )
1099{
82b978d7
RD
1100 wxASSERT_MSG( (m_widget != NULL), wxT("invalid frame") );
1101
cb8cc250
WS
1102 if ( title == m_title )
1103 return;
1104
7d9f12f3 1105 m_title = title;
cb8cc250 1106
fab591c5 1107 gtk_window_set_title( GTK_WINDOW(m_widget), wxGTK_CONV( title ) );
7d9f12f3
VS
1108}
1109
f618020a
MB
1110void wxTopLevelWindowGTK::SetIcon( const wxIcon &icon )
1111{
1112 SetIcons( wxIconBundle( icon ) );
1113}
1114
1115void wxTopLevelWindowGTK::SetIcons( const wxIconBundle &icons )
1116{
82b978d7 1117 wxASSERT_MSG( (m_widget != NULL), wxT("invalid frame") );
f618020a
MB
1118
1119 wxTopLevelWindowBase::SetIcons( icons );
1120
87e53e2a
VS
1121 GList *list = NULL;
1122 size_t max = icons.m_icons.GetCount();
1123
1124 for (size_t i = 0; i < max; i++)
52d6235d 1125 {
87e53e2a
VS
1126 if (icons.m_icons[i].Ok())
1127 {
1128 list = g_list_prepend(list, icons.m_icons[i].GetPixbuf());
1129 }
1130 }
1131 gtk_window_set_icon_list(GTK_WINDOW(m_widget), list);
1132 g_list_free(list);
f618020a
MB
1133}
1134
7d9f12f3
VS
1135// ----------------------------------------------------------------------------
1136// frame state: maximized/iconized/normal
1137// ----------------------------------------------------------------------------
1138
8805e155 1139void wxTopLevelWindowGTK::Maximize(bool maximize)
7d9f12f3 1140{
8805e155
RR
1141 if (maximize)
1142 gtk_window_maximize( GTK_WINDOW( m_widget ) );
1143 else
1144 gtk_window_unmaximize( GTK_WINDOW( m_widget ) );
7d9f12f3
VS
1145}
1146
1147bool wxTopLevelWindowGTK::IsMaximized() const
1148{
d8e1fe80
VS
1149 if(!m_widget->window)
1150 return false;
1151
1152 return gdk_window_get_state(m_widget->window) & GDK_WINDOW_STATE_MAXIMIZED;
7d9f12f3
VS
1153}
1154
1155void wxTopLevelWindowGTK::Restore()
1156{
8805e155
RR
1157 // "Present" seems similar enough to "restore"
1158 gtk_window_present( GTK_WINDOW( m_widget ) );
7d9f12f3
VS
1159}
1160
1161void wxTopLevelWindowGTK::Iconize( bool iconize )
1162{
8805e155
RR
1163 if (iconize)
1164 gtk_window_iconify( GTK_WINDOW( m_widget ) );
1165 else
1166 gtk_window_deiconify( GTK_WINDOW( m_widget ) );
7d9f12f3
VS
1167}
1168
1169bool wxTopLevelWindowGTK::IsIconized() const
1170{
1171 return m_isIconized;
1172}
1173
1174void wxTopLevelWindowGTK::SetIconizeState(bool iconize)
1175{
1176 if ( iconize != m_isIconized )
1177 {
1178 m_isIconized = iconize;
1179 (void)SendIconizeEvent(iconize);
1180 }
1181}
1182
5152b0e5
JS
1183void wxTopLevelWindowGTK::AddGrab()
1184{
1185 if (!m_grabbed)
1186 {
0a164d4c 1187 m_grabbed = true;
5152b0e5 1188 gtk_grab_add( m_widget );
924b84ab 1189 wxEventLoop().Run();
5152b0e5
JS
1190 gtk_grab_remove( m_widget );
1191 }
1192}
1193
1194void wxTopLevelWindowGTK::RemoveGrab()
1195{
1196 if (m_grabbed)
1197 {
1198 gtk_main_quit();
0a164d4c 1199 m_grabbed = false;
5152b0e5
JS
1200 }
1201}
801225c1 1202
1542ea39
RD
1203
1204// helper
1205static bool do_shape_combine_region(GdkWindow* window, const wxRegion& region)
1206{
1207 if (window)
1208 {
1209 if (region.IsEmpty())
1210 {
1211 gdk_window_shape_combine_mask(window, NULL, 0, 0);
1212 }
1213 else
1214 {
0a164d4c 1215 gdk_window_shape_combine_region(window, region.GetRegion(), 0, 0);
0a164d4c 1216 return true;
1542ea39
RD
1217 }
1218 }
0a164d4c 1219 return false;
1542ea39
RD
1220}
1221
1222
1223bool wxTopLevelWindowGTK::SetShape(const wxRegion& region)
1224{
0a164d4c 1225 wxCHECK_MSG( HasFlag(wxFRAME_SHAPED), false,
6a7e6411
RD
1226 _T("Shaped windows must be created with the wxFRAME_SHAPED style."));
1227
1542ea39
RD
1228 GdkWindow *window = NULL;
1229 if (m_wxwindow)
1230 {
1231 window = GTK_PIZZA(m_wxwindow)->bin_window;
1232 do_shape_combine_region(window, region);
1233 }
1234 window = m_widget->window;
1235 return do_shape_combine_region(window, region);
1236}
1237
6b30a44e 1238bool wxTopLevelWindowGTK::IsActive()
35ff90a0 1239{
06fda9e8 1240 return (this == (wxTopLevelWindowGTK*)g_activeFrame);
35ff90a0 1241}
dca92ddf
MR
1242
1243void wxTopLevelWindowGTK::RequestUserAttention(int flags)
1244{
1245 bool new_hint_value = false;
1246
1247 // FIXME: This is a workaround to focus handling problem
1248 // If RequestUserAttention is called for example right after a wxSleep, OnInternalIdle hasn't
1249 // yet been processed, and the internal focus system is not up to date yet.
1250 // wxYieldIfNeeded ensures the processing of it, but can have unwanted side effects - MR
1251 ::wxYieldIfNeeded();
1252
dca92ddf 1253 if(m_urgency_hint >= 0)
92ed8bec 1254 g_source_remove(m_urgency_hint);
dca92ddf 1255
ef1a9be4 1256 m_urgency_hint = -2;
dca92ddf
MR
1257
1258 if( GTK_WIDGET_REALIZED(m_widget) && !IsActive() )
1259 {
1260 new_hint_value = true;
1261
1262 if (flags & wxUSER_ATTENTION_INFO)
1263 {
92ed8bec 1264 m_urgency_hint = g_timeout_add(5000, (GSourceFunc)gtk_frame_urgency_timer_callback, this);
dca92ddf 1265 } else {
ef1a9be4 1266 m_urgency_hint = -1;
dca92ddf
MR
1267 }
1268 }
1269
2ec371fd 1270#if GTK_CHECK_VERSION(2,7,0)
dca92ddf
MR
1271 if(!gtk_check_version(2,7,0))
1272 gtk_window_set_urgency_hint(GTK_WINDOW( m_widget ), new_hint_value);
1273 else
1274#endif
1275 wxgtk_window_set_urgency_hint(GTK_WINDOW( m_widget ), new_hint_value);
1276}
015dca24
MR
1277
1278void wxTopLevelWindowGTK::SetWindowStyleFlag( long style )
1279{
7e3edf92 1280#if defined(__WXGTK24__) || GTK_CHECK_VERSION(2,2,0)
015dca24
MR
1281 // Store which styles were changed
1282 long styleChanges = style ^ m_windowStyle;
7e3edf92 1283#endif
015dca24
MR
1284
1285 // Process wxWindow styles. This also updates the internal variable
1286 // Therefore m_windowStyle bits carry now the _new_ style values
1287 wxWindow::SetWindowStyleFlag(style);
1288
1289 // just return for now if widget does not exist yet
1290 if (!m_widget)
1291 return;
1292
1293#ifdef __WXGTK24__
1294 if ( (styleChanges & wxSTAY_ON_TOP) && !gtk_check_version(2,4,0) )
1295 gtk_window_set_keep_above(GTK_WINDOW(m_widget), m_windowStyle & wxSTAY_ON_TOP);
defdd888 1296#endif // GTK+ 2.4
8fb82418
MR
1297#if GTK_CHECK_VERSION(2,2,0)
1298 if ( (styleChanges & wxFRAME_NO_TASKBAR) && !gtk_check_version(2,2,0) )
1299 {
1300 gtk_window_set_skip_taskbar_hint(GTK_WINDOW(m_widget), m_windowStyle & wxFRAME_NO_TASKBAR);
1301 }
defdd888 1302#endif // GTK+ 2.2
015dca24 1303}
07e49707
MR
1304
1305#include <X11/Xlib.h>
1306
1307/* Get the X Window between child and the root window.
1308 This should usually be the WM managed XID */
1309static Window wxGetTopmostWindowX11(Display *dpy, Window child)
1310{
1311 Window root, parent;
1312 Window* children;
1313 unsigned int nchildren;
1314
1315 XQueryTree(dpy, child, &root, &parent, &children, &nchildren);
1316 XFree(children);
1317
1318 while (parent != root) {
1319 child = parent;
1320 XQueryTree(dpy, child, &root, &parent, &children, &nchildren);
1321 XFree(children);
1322 }
1323
1324 return child;
1325}
1326
1327bool wxTopLevelWindowGTK::SetTransparent(wxByte alpha)
1328{
3eecbda8 1329 if (!m_widget || !m_widget->window)
07e49707
MR
1330 return false;
1331
1332 Display* dpy = GDK_WINDOW_XDISPLAY (m_widget->window);
1333 // We need to get the X Window that has the root window as the immediate parent
1334 // and m_widget->window as a child. This should be the X Window that the WM manages and
1335 // from which the opacity property is checked from.
1336 Window win = wxGetTopmostWindowX11(dpy, GDK_WINDOW_XID (m_widget->window));
1337
1338 unsigned int opacity = alpha * 0x1010101;
1339
1340 // Using pure Xlib to not have a GTK version check mess due to gtk2.0 not having GdkDisplay
1341 if (alpha == 0xff)
1342 XDeleteProperty(dpy, win, XInternAtom(dpy, "_NET_WM_WINDOW_OPACITY", False));
1343 else
1344 XChangeProperty(dpy, win, XInternAtom(dpy, "_NET_WM_WINDOW_OPACITY", False),
1345 XA_CARDINAL, 32, PropModeReplace,
1346 (unsigned char *) &opacity, 1L);
1347 XSync(dpy, False);
1348 return true;
1349}
1350
1351bool wxTopLevelWindowGTK::CanSetTransparent()
1352{
60169b7a
MR
1353#if GTK_CHECK_VERSION(2,10,0)
1354 if (!gtk_check_version(2,10,0))
1355 {
1356 if (gtk_widget_is_composited (m_widget))
1357 return true;
1358 }
1359 else
1360#endif // In case of lower versions than gtk+-2.10.0 we could look for _NET_WM_CM_Sn ourselves
1361 {
1362 return false;
1363 }
1364
1365#if 0 // Don't be optimistic here for the sake of wxAUI
07e49707
MR
1366 int opcode, event, error;
1367 // Check for the existence of a RGBA visual instead?
1368 return XQueryExtension(gdk_x11_get_default_xdisplay (),
1369 "Composite", &opcode, &event, &error);
60169b7a 1370#endif
07e49707 1371}