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