]> git.saurik.com Git - wxWidgets.git/blob - 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
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 *WXUNUSED(widget),
273 GdkEventConfigure *WXUNUSED(event),
274 wxTopLevelWindowGTK *win )
275 {
276 if (!win->m_hasVMT || !win->IsShown())
277 return FALSE;
278
279
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;
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 }
292 }
293
294 //-----------------------------------------------------------------------------
295 // "realize" from m_widget
296 //-----------------------------------------------------------------------------
297
298 // we cannot MWM hints and icons before the widget has been realized,
299 // so we do this directly after realization
300
301 extern "C" {
302 static void
303 gtk_frame_realized_callback( GtkWidget * WXUNUSED(widget),
304 wxTopLevelWindowGTK *win )
305 {
306 // All this is for Motif Window Manager "hints" and is supposed to be
307 // recognized by other WM as well. Not tested.
308 gdk_window_set_decorations(win->m_widget->window,
309 (GdkWMDecoration)win->m_gdkDecor);
310 gdk_window_set_functions(win->m_widget->window,
311 (GdkWMFunction)win->m_gdkFunc);
312
313 // GTK's shrinking/growing policy
314 if ((win->m_gdkFunc & GDK_FUNC_RESIZE) == 0)
315 gtk_window_set_resizable(GTK_WINDOW(win->m_widget), FALSE);
316 else
317 gtk_window_set_policy(GTK_WINDOW(win->m_widget), 1, 1, 1);
318
319 // reset the icon
320 wxIconBundle iconsOld = win->GetIcons();
321 if ( !iconsOld.IsEmpty() )
322 {
323 win->SetIcon( wxNullIcon );
324 win->SetIcons( iconsOld );
325 }
326 }
327 }
328
329 //-----------------------------------------------------------------------------
330 // "map_event" from m_widget
331 //-----------------------------------------------------------------------------
332
333 extern "C" {
334 static void
335 gtk_frame_map_callback( GtkWidget * WXUNUSED(widget),
336 GdkEvent * WXUNUSED(event),
337 wxTopLevelWindow *win )
338 {
339 win->SetIconizeState(false);
340 }
341 }
342
343 //-----------------------------------------------------------------------------
344 // "unmap_event" from m_widget
345 //-----------------------------------------------------------------------------
346
347 extern "C" {
348 static void
349 gtk_frame_unmap_callback( GtkWidget * WXUNUSED(widget),
350 GdkEvent * WXUNUSED(event),
351 wxTopLevelWindow *win )
352 {
353 win->SetIconizeState(true);
354 }
355 }
356
357 //-----------------------------------------------------------------------------
358 // "expose_event" of m_client
359 //-----------------------------------------------------------------------------
360
361 extern "C" {
362 static gboolean
363 gtk_window_expose_callback( GtkWidget *widget,
364 GdkEventExpose *gdk_event,
365 wxWindow *win )
366 {
367 GtkPizza *pizza = GTK_PIZZA(widget);
368
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);
376
377 return FALSE;
378 }
379 }
380
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
391 * virtual function here as wxWidgets requires different ways to insert
392 * a child in container classes. */
393
394 static void wxInsertChildInTopLevelWindow( wxTopLevelWindowGTK* parent, wxWindow* child )
395 {
396 wxASSERT( GTK_IS_WIDGET(child->m_widget) );
397
398 if (!parent->m_insertInClientArea)
399 {
400 // these are outside the client area
401 wxTopLevelWindowGTK* frame = (wxTopLevelWindowGTK*) parent;
402 gtk_pizza_put( GTK_PIZZA(frame->m_mainWidget),
403 child->m_widget,
404 child->m_x,
405 child->m_y,
406 child->m_width,
407 child->m_height );
408 }
409 else
410 {
411 // these are inside the client area
412 gtk_pizza_put( GTK_PIZZA(parent->m_wxwindow),
413 child->m_widget,
414 child->m_x,
415 child->m_y,
416 child->m_width,
417 child->m_height );
418 }
419 }
420
421 // ----------------------------------------------------------------------------
422 // wxTopLevelWindowGTK creation
423 // ----------------------------------------------------------------------------
424
425 void wxTopLevelWindowGTK::Init()
426 {
427 m_sizeSet = false;
428 m_miniEdge = 0;
429 m_miniTitle = 0;
430 m_mainWidget = (GtkWidget*) NULL;
431 m_insertInClientArea = true;
432 m_isIconized = false;
433 m_fsIsShowing = false;
434 m_fsSaveFlag = 0;
435 m_themeEnabled = true;
436 m_gdkDecor = m_gdkFunc = 0;
437 m_grabbed = false;
438
439 m_urgency_hint = -2;
440 }
441
442 bool wxTopLevelWindowGTK::Create( wxWindow *parent,
443 wxWindowID id,
444 const wxString& title,
445 const wxPoint& pos,
446 const wxSize& sizeOrig,
447 long style,
448 const wxString &name )
449 {
450 // always create a frame of some reasonable, even if arbitrary, size (at
451 // least for MSW compatibility)
452 wxSize size = sizeOrig;
453 size.x = WidthDefault(size.x);
454 size.y = HeightDefault(size.y);
455
456 wxTopLevelWindows.Append( this );
457
458 m_needParent = false;
459
460 if (!PreCreation( parent, pos, size ) ||
461 !CreateBase( parent, id, pos, size, style, wxDefaultValidator, name ))
462 {
463 wxFAIL_MSG( wxT("wxTopLevelWindowGTK creation failed") );
464 return false;
465 }
466
467 m_title = title;
468
469 m_insertCallback = (wxInsertChildFunction) wxInsertChildInTopLevelWindow;
470
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 {
475 if (GetExtraStyle() & wxTOPLEVEL_EX_DIALOG)
476 {
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);
484 }
485 else
486 {
487 m_widget = gtk_window_new(GTK_WINDOW_TOPLEVEL);
488 #if GTK_CHECK_VERSION(2,1,0)
489 if (!gtk_check_version(2,1,0))
490 {
491 if (style & wxFRAME_TOOL_WINDOW)
492 {
493 gtk_window_set_type_hint(GTK_WINDOW(m_widget),
494 GDK_WINDOW_TYPE_HINT_UTILITY);
495
496 // On some WMs, like KDE, a TOOL_WINDOW will still show
497 // on the taskbar, but on Gnome a TOOL_WINDOW will not.
498 // For consistency between WMs and with Windows, we
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 }
504 }
505 #endif
506 }
507 }
508
509 wxWindow *topParent = wxGetTopLevelParent(m_parent);
510 if (topParent && (((GTK_IS_WINDOW(topParent->m_widget)) &&
511 (GetExtraStyle() & wxTOPLEVEL_EX_DIALOG)) ||
512 (style & wxFRAME_FLOAT_ON_PARENT)))
513 {
514 gtk_window_set_transient_for( GTK_WINDOW(m_widget),
515 GTK_WINDOW(topParent->m_widget) );
516 }
517
518 #if GTK_CHECK_VERSION(2,2,0)
519 if (!gtk_check_version(2,2,0))
520 {
521 if (style & wxFRAME_NO_TASKBAR)
522 {
523 gtk_window_set_skip_taskbar_hint(GTK_WINDOW(m_widget), TRUE);
524 }
525 }
526 #endif
527
528 #ifdef __WXGTK24__
529 if (!gtk_check_version(2,4,0))
530 {
531 if (style & wxSTAY_ON_TOP)
532 {
533 gtk_window_set_keep_above(GTK_WINDOW(m_widget), TRUE);
534 }
535 }
536 #endif
537
538 #if 0
539 if (!name.empty())
540 gtk_window_set_role( GTK_WINDOW(m_widget), wxGTK_CONV( name ) );
541 #endif
542
543 gtk_window_set_title( GTK_WINDOW(m_widget), wxGTK_CONV( title ) );
544 GTK_WIDGET_UNSET_FLAGS( m_widget, GTK_CAN_FOCUS );
545
546 g_signal_connect (m_widget, "delete_event",
547 G_CALLBACK (gtk_frame_delete_callback), this);
548
549 // m_mainWidget holds the toolbar, the menubar and the client area
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
555 if (m_miniEdge == 0) // wxMiniFrame has its own version.
556 {
557 // For m_mainWidget themes
558 g_signal_connect (m_mainWidget, "expose_event",
559 G_CALLBACK (gtk_window_expose_callback), this);
560 }
561
562 // m_wxwindow only represents the client area without toolbar and menubar
563 m_wxwindow = gtk_pizza_new();
564 gtk_widget_show( m_wxwindow );
565 gtk_container_add( GTK_CONTAINER(m_mainWidget), m_wxwindow );
566
567 // we donm't allow the frame to get the focus as otherwise
568 // the frame will grab it at arbitrary focus changes
569 GTK_WIDGET_UNSET_FLAGS( m_wxwindow, GTK_CAN_FOCUS );
570
571 if (m_parent) m_parent->AddChild( this );
572
573 // the user resized the frame by dragging etc.
574 g_signal_connect (m_widget, "size_allocate",
575 G_CALLBACK (gtk_frame_size_callback), this);
576
577 g_signal_connect (m_widget, "size_request",
578 G_CALLBACK (wxgtk_tlw_size_request_callback), this);
579 PostCreation();
580
581 if ((m_x != -1) || (m_y != -1))
582 gtk_widget_set_uposition( m_widget, m_x, m_y );
583
584 gtk_window_set_default_size( GTK_WINDOW(m_widget), m_width, m_height );
585
586 // we cannot set MWM hints and icons before the widget has
587 // been realized, so we do this directly after realization
588 g_signal_connect (m_widget, "realize",
589 G_CALLBACK (gtk_frame_realized_callback), this);
590
591 // map and unmap for iconized state
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);
596
597 // the only way to get the window size is to connect to this event
598 g_signal_connect (m_widget, "configure_event",
599 G_CALLBACK (gtk_frame_configure_callback), this);
600
601 // activation
602 g_signal_connect_after (m_widget, "focus_in_event",
603 G_CALLBACK (gtk_frame_focus_in_callback), this);
604 g_signal_connect_after (m_widget, "focus_out_event",
605 G_CALLBACK (gtk_frame_focus_out_callback), this);
606
607 // decorations
608 if ((style & wxSIMPLE_BORDER) || (style & wxNO_BORDER))
609 {
610 m_gdkDecor = 0;
611 m_gdkFunc = 0;
612 }
613 else
614 if (m_miniEdge > 0)
615 {
616 m_gdkDecor = 0;
617 m_gdkFunc = 0;
618
619 if ((style & wxRESIZE_BORDER) != 0)
620 m_gdkFunc |= GDK_FUNC_RESIZE;
621 }
622 else
623 {
624 m_gdkDecor = (long) GDK_DECOR_BORDER;
625 m_gdkFunc = (long) GDK_FUNC_MOVE;
626
627 // All this is for Motif Window Manager "hints" and is supposed to be
628 // recognized by other WMs as well.
629 if ((style & wxCAPTION) != 0)
630 {
631 m_gdkDecor |= GDK_DECOR_TITLE;
632 }
633 if ((style & wxCLOSE_BOX) != 0)
634 {
635 m_gdkFunc |= GDK_FUNC_CLOSE;
636 }
637 if ((style & wxSYSTEM_MENU) != 0)
638 {
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
658 return true;
659 }
660
661 wxTopLevelWindowGTK::~wxTopLevelWindowGTK()
662 {
663 if (m_grabbed)
664 {
665 wxFAIL_MSG(_T("Window still grabbed"));
666 RemoveGrab();
667 }
668
669 m_isBeingDeleted = true;
670
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 }
676
677 if (g_activeFrame == this)
678 g_activeFrame = NULL;
679 if (g_lastActiveFrame == this)
680 g_lastActiveFrame = NULL;
681 }
682
683 bool wxTopLevelWindowGTK::EnableCloseButton( bool enable )
684 {
685 if (enable)
686 m_gdkFunc |= GDK_FUNC_CLOSE;
687 else
688 m_gdkFunc &= ~GDK_FUNC_CLOSE;
689
690 if (GTK_WIDGET_REALIZED(m_widget) && (m_widget->window))
691 gdk_window_set_functions( m_widget->window, (GdkWMFunction)m_gdkFunc );
692
693 return true;
694 }
695
696 bool wxTopLevelWindowGTK::ShowFullScreen(bool show, long style )
697 {
698 if (show == m_fsIsShowing)
699 return false; // return what?
700
701 m_fsIsShowing = show;
702
703 wxX11FullScreenMethod method =
704 wxGetFullScreenMethodX11((WXDisplay*)GDK_DISPLAY(),
705 (WXWindow)GDK_ROOT_WINDOW());
706
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.
712 if ( (method == wxX11_FS_WMSPEC) && !gtk_check_version(2,2,0) )
713 {
714 if (show)
715 {
716 m_fsSaveFlag = style;
717 gtk_window_fullscreen( GTK_WINDOW( m_widget ) );
718 }
719 else
720 {
721 m_fsSaveFlag = 0;
722 gtk_window_unfullscreen( GTK_WINDOW( m_widget ) );
723 }
724 }
725 else
726 #endif // GTK+ >= 2.2.0
727 {
728 GdkWindow *window = m_widget->window;
729
730 if (show)
731 {
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 }
764 else // hide
765 {
766 m_fsSaveFlag = 0;
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);
783 }
784 }
785
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
791 return true;
792 }
793
794 // ----------------------------------------------------------------------------
795 // overridden wxWindow methods
796 // ----------------------------------------------------------------------------
797
798 bool wxTopLevelWindowGTK::Show( bool show )
799 {
800 wxASSERT_MSG( (m_widget != NULL), wxT("invalid frame") );
801
802 if (show == IsShown())
803 return true;
804
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
812 GtkOnSize();
813 }
814
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 );
820
821 return wxWindow::Show( show );
822 }
823
824 void wxTopLevelWindowGTK::Raise()
825 {
826 gtk_window_present( GTK_WINDOW( m_widget ) );
827 }
828
829 void 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
834 // ----------------------------------------------------------------------------
835 // window geometry
836 // ----------------------------------------------------------------------------
837
838 void wxTopLevelWindowGTK::GTKDoGetSize(int *width, int *height) const
839 {
840 return wxTopLevelWindowBase::DoGetSize(width, height);
841 }
842
843 void 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
889 void wxTopLevelWindowGTK::DoSetSize( int x, int y, int width, int height, int sizeFlags )
890 {
891 wxCHECK_RET( m_widget, wxT("invalid frame") );
892
893 // this shouldn't happen: wxFrame, wxMDIParentFrame and wxMDIChildFrame have m_wxwindow
894 wxASSERT_MSG( (m_wxwindow != NULL), wxT("invalid frame") );
895
896
897 // deal with the position first
898 int old_x = m_x;
899 int old_y = m_y;
900
901 if ( !(sizeFlags & wxSIZE_ALLOW_MINUS_ONE) )
902 {
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;
908 }
909 else // wxSIZE_ALLOW_MINUS_ONE
910 {
911 m_x = x;
912 m_y = y;
913 }
914
915 if ( m_x != old_x || m_y != old_y )
916 {
917 gtk_window_move( GTK_WINDOW(m_widget), m_x, m_y );
918 }
919
920
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);
929
930 int wUndec,
931 hUndec;
932 GTKDoGetSize(&wUndec, &hUndec);
933
934 if ( width != -1 )
935 width -= wTotal - wUndec;
936 if ( height != -1 )
937 height -= hTotal - hUndec;
938 }
939
940 GTKDoSetSize(width, height);
941 }
942
943 void 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
951 GTKDoGetSize(width, height);
952 return;
953 }
954
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;
962 }
963
964 void wxTopLevelWindowGTK::DoGetClientSize( int *width, int *height ) const
965 {
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
978 wxASSERT_MSG( (m_widget != NULL), wxT("invalid frame") );
979
980 if (height)
981 {
982 *height = m_height - 2 * m_miniEdge - m_miniTitle;
983 if (*height < 0)
984 *height = 0;
985 }
986 if (width)
987 {
988 *width = m_width - 2 * m_miniEdge;
989 if (*width < 0)
990 *width = 0;
991 }
992 }
993
994 void wxTopLevelWindowGTK::DoSetClientSize( int width, int height )
995 {
996 GTKDoSetSize(width + m_miniEdge*2, height + m_miniEdge*2 + m_miniTitle);
997 }
998
999 void wxTopLevelWindowGTK::DoSetSizeHints( int minW, int minH,
1000 int maxW, int maxH,
1001 int incW, int incH )
1002 {
1003 wxTopLevelWindowBase::DoSetSizeHints( minW, minH, maxW, maxH, incW, incH );
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)
1022 {
1023 hints_mask |= GDK_HINT_RESIZE_INC;
1024 hints.width_inc = incW > 0 ? incW : 1;
1025 hints.height_inc = incH > 0 ? incH : 1;
1026 }
1027 gtk_window_set_geometry_hints(
1028 (GtkWindow*)m_widget, NULL, &hints, (GdkWindowHints)hints_mask);
1029 }
1030
1031
1032 void 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.
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;
1075 if (client_w < 0)
1076 client_w = 0;
1077 if (client_h < 0)
1078 client_h = 0;
1079
1080 // Let the parent perform the resize
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 {
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.
1089 }
1090
1091 m_sizeSet = true;
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
1098 m_resizing = false;
1099 }
1100
1101 void wxTopLevelWindowGTK::OnInternalIdle()
1102 {
1103 if (!m_sizeSet && GTK_WIDGET_REALIZED(m_wxwindow))
1104 {
1105 GtkOnSize();
1106
1107 // we'll come back later
1108 return;
1109 }
1110
1111 // set the focus if not done yet and if we can already do it
1112 if ( GTK_WIDGET_REALIZED(m_wxwindow) )
1113 {
1114 if ( g_delayedFocus &&
1115 wxGetTopLevelParent((wxWindow*)g_delayedFocus) == this )
1116 {
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
1122 g_delayedFocus->SetFocus();
1123 g_delayedFocus = NULL;
1124 }
1125 }
1126
1127 wxWindow::OnInternalIdle();
1128
1129 // Synthetize activate events.
1130 if ( g_sendActivateEvent != -1 )
1131 {
1132 bool activate = g_sendActivateEvent != 0;
1133
1134 // if (!activate) wxPrintf( wxT("de") );
1135 // wxPrintf( wxT("activate\n") );
1136
1137 // do it only once
1138 g_sendActivateEvent = -1;
1139
1140 wxTheApp->SetActive(activate, (wxWindow *)g_lastActiveFrame);
1141 }
1142 }
1143
1144 // ----------------------------------------------------------------------------
1145 // frame title/icon
1146 // ----------------------------------------------------------------------------
1147
1148 void wxTopLevelWindowGTK::SetTitle( const wxString &title )
1149 {
1150 wxASSERT_MSG( (m_widget != NULL), wxT("invalid frame") );
1151
1152 if ( title == m_title )
1153 return;
1154
1155 m_title = title;
1156
1157 gtk_window_set_title( GTK_WINDOW(m_widget), wxGTK_CONV( title ) );
1158 }
1159
1160 void wxTopLevelWindowGTK::SetIcons( const wxIconBundle &icons )
1161 {
1162 wxASSERT_MSG( (m_widget != NULL), wxT("invalid frame") );
1163
1164 wxTopLevelWindowBase::SetIcons( icons );
1165
1166 GList *list = NULL;
1167
1168 const size_t numIcons = icons.GetIconCount();
1169 for ( size_t i = 0; i < numIcons; i++ )
1170 {
1171 list = g_list_prepend(list, icons.GetIconByIndex(i).GetPixbuf());
1172 }
1173
1174 gtk_window_set_icon_list(GTK_WINDOW(m_widget), list);
1175 g_list_free(list);
1176 }
1177
1178 // ----------------------------------------------------------------------------
1179 // frame state: maximized/iconized/normal
1180 // ----------------------------------------------------------------------------
1181
1182 void wxTopLevelWindowGTK::Maximize(bool maximize)
1183 {
1184 if (maximize)
1185 gtk_window_maximize( GTK_WINDOW( m_widget ) );
1186 else
1187 gtk_window_unmaximize( GTK_WINDOW( m_widget ) );
1188 }
1189
1190 bool wxTopLevelWindowGTK::IsMaximized() const
1191 {
1192 if(!m_widget->window)
1193 return false;
1194
1195 return gdk_window_get_state(m_widget->window) & GDK_WINDOW_STATE_MAXIMIZED;
1196 }
1197
1198 void wxTopLevelWindowGTK::Restore()
1199 {
1200 // "Present" seems similar enough to "restore"
1201 gtk_window_present( GTK_WINDOW( m_widget ) );
1202 }
1203
1204 void wxTopLevelWindowGTK::Iconize( bool iconize )
1205 {
1206 if (iconize)
1207 gtk_window_iconify( GTK_WINDOW( m_widget ) );
1208 else
1209 gtk_window_deiconify( GTK_WINDOW( m_widget ) );
1210 }
1211
1212 bool wxTopLevelWindowGTK::IsIconized() const
1213 {
1214 return m_isIconized;
1215 }
1216
1217 void wxTopLevelWindowGTK::SetIconizeState(bool iconize)
1218 {
1219 if ( iconize != m_isIconized )
1220 {
1221 m_isIconized = iconize;
1222 (void)SendIconizeEvent(iconize);
1223 }
1224 }
1225
1226 void wxTopLevelWindowGTK::AddGrab()
1227 {
1228 if (!m_grabbed)
1229 {
1230 m_grabbed = true;
1231 gtk_grab_add( m_widget );
1232 wxEventLoop().Run();
1233 gtk_grab_remove( m_widget );
1234 }
1235 }
1236
1237 void wxTopLevelWindowGTK::RemoveGrab()
1238 {
1239 if (m_grabbed)
1240 {
1241 gtk_main_quit();
1242 m_grabbed = false;
1243 }
1244 }
1245
1246
1247 // helper
1248 static 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 {
1258 gdk_window_shape_combine_region(window, region.GetRegion(), 0, 0);
1259 return true;
1260 }
1261 }
1262 return false;
1263 }
1264
1265
1266 bool wxTopLevelWindowGTK::SetShape(const wxRegion& region)
1267 {
1268 wxCHECK_MSG( HasFlag(wxFRAME_SHAPED), false,
1269 _T("Shaped windows must be created with the wxFRAME_SHAPED style."));
1270
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
1281 bool wxTopLevelWindowGTK::IsActive()
1282 {
1283 return (this == (wxTopLevelWindowGTK*)g_activeFrame);
1284 }
1285
1286 void 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
1296 if(m_urgency_hint >= 0)
1297 g_source_remove(m_urgency_hint);
1298
1299 m_urgency_hint = -2;
1300
1301 if( GTK_WIDGET_REALIZED(m_widget) && !IsActive() )
1302 {
1303 new_hint_value = true;
1304
1305 if (flags & wxUSER_ATTENTION_INFO)
1306 {
1307 m_urgency_hint = g_timeout_add(5000, (GSourceFunc)gtk_frame_urgency_timer_callback, this);
1308 } else {
1309 m_urgency_hint = -1;
1310 }
1311 }
1312
1313 #if GTK_CHECK_VERSION(2,7,0)
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 }
1320
1321 void wxTopLevelWindowGTK::SetWindowStyleFlag( long style )
1322 {
1323 #if defined(__WXGTK24__) || GTK_CHECK_VERSION(2,2,0)
1324 // Store which styles were changed
1325 long styleChanges = style ^ m_windowStyle;
1326 #endif
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);
1339 #endif // GTK+ 2.4
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 }
1345 #endif // GTK+ 2.2
1346 }
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 */
1352 static 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
1370 bool wxTopLevelWindowGTK::SetTransparent(wxByte alpha)
1371 {
1372 if (!m_widget || !m_widget->window)
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
1394 bool wxTopLevelWindowGTK::CanSetTransparent()
1395 {
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
1403 #if GTK_CHECK_VERSION(2,10,0)
1404 if (!gtk_check_version(2,10,0))
1405 {
1406 return (gtk_widget_is_composited (m_widget));
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
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);
1419 #endif
1420 }