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