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