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