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