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