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