]> git.saurik.com Git - wxWidgets.git/blame - src/gtk1/toplevel.cpp
respect GTK+'s theme tooltip colour settings
[wxWidgets.git] / src / gtk1 / toplevel.cpp
CommitLineData
7d9f12f3
VS
1/////////////////////////////////////////////////////////////////////////////
2// Name: toplevel.cpp
3// Purpose:
4// Author: Robert Roebling
5// Id: $Id$
6// Copyright: (c) 1998 Robert Roebling
65571936 7// Licence: wxWindows licence
7d9f12f3
VS
8/////////////////////////////////////////////////////////////////////////////
9
10// ============================================================================
11// declarations
12// ============================================================================
13
14// ----------------------------------------------------------------------------
15// headers
16// ----------------------------------------------------------------------------
17
14f355c2 18#if defined(__GNUG__) && !defined(NO_GCC_PRAGMA)
7d9f12f3
VS
19 #pragma implementation "toplevel.h"
20#endif
21
14f355c2
VS
22// For compilers that support precompilation, includes "wx.h".
23#include "wx/wxprec.h"
24
7d9f12f3
VS
25#ifdef __VMS
26#define XIconifyWindow XICONIFYWINDOW
27#endif
28
29#include "wx/defs.h"
30
2b5f62a0 31#include "wx/log.h"
7d9f12f3
VS
32#include "wx/dialog.h"
33#include "wx/control.h"
34#include "wx/app.h"
35#include "wx/dcclient.h"
fab591c5 36#include "wx/gtk/private.h"
8166ab43 37#include "wx/timer.h"
ca06ee0d 38#include "wx/settings.h"
7d9f12f3
VS
39
40#include <glib.h>
41#include <gdk/gdk.h>
42#include <gtk/gtk.h>
43#include <gdk/gdkkeysyms.h>
44#include <gdk/gdkx.h>
45
46#include "wx/gtk/win_gtk.h"
47
f618020a
MB
48#include "wx/unix/utilsx11.h"
49
8a9650ea
RR
50// XA_CARDINAL
51#include <X11/Xatom.h>
52
7d9f12f3
VS
53// ----------------------------------------------------------------------------
54// idle system
55// ----------------------------------------------------------------------------
56
57extern void wxapp_install_idle_handler();
58extern bool g_isIdle;
7d9f12f3 59
7d9f12f3
VS
60// ----------------------------------------------------------------------------
61// data
62// ----------------------------------------------------------------------------
63
d7fa7eaa
RR
64extern wxList wxPendingDelete;
65
66extern int g_openDialogs;
67extern wxWindowGTK *g_delayedFocus;
7d9f12f3 68
7d9f12f3
VS
69//-----------------------------------------------------------------------------
70// "focus" from m_window
71//-----------------------------------------------------------------------------
72
73static gint gtk_frame_focus_callback( GtkWidget *widget, GtkDirectionType WXUNUSED(d), wxWindow *WXUNUSED(win) )
74{
75 if (g_isIdle)
76 wxapp_install_idle_handler();
77
78 // This disables GTK's tab traversal
79 gtk_signal_emit_stop_by_name( GTK_OBJECT(widget), "focus" );
80 return TRUE;
81}
82
83//-----------------------------------------------------------------------------
84// "size_allocate"
85//-----------------------------------------------------------------------------
86
87static void gtk_frame_size_callback( GtkWidget *WXUNUSED(widget), GtkAllocation* alloc, wxTopLevelWindowGTK *win )
88{
89 if (g_isIdle)
90 wxapp_install_idle_handler();
91
92 if (!win->m_hasVMT)
93 return;
94
95 if ((win->m_width != alloc->width) || (win->m_height != alloc->height))
96 {
97/*
98 wxPrintf( "OnSize from " );
99 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
100 wxPrintf( win->GetClassInfo()->GetClassName() );
101 wxPrintf( " %d %d %d %d\n", (int)alloc->x,
102 (int)alloc->y,
103 (int)alloc->width,
104 (int)alloc->height );
105*/
106
107 win->m_width = alloc->width;
108 win->m_height = alloc->height;
109 win->m_queuedFullRedraw = TRUE;
110 win->GtkUpdateSize();
111 }
112}
113
114//-----------------------------------------------------------------------------
115// "delete_event"
116//-----------------------------------------------------------------------------
117
118static gint gtk_frame_delete_callback( GtkWidget *WXUNUSED(widget), GdkEvent *WXUNUSED(event), wxTopLevelWindowGTK *win )
119{
120 if (g_isIdle)
121 wxapp_install_idle_handler();
122
123 if (win->IsEnabled() &&
5152b0e5
JS
124 (g_openDialogs == 0 || (win->GetExtraStyle() & wxTOPLEVEL_EX_DIALOG) ||
125 win->IsGrabbed()))
7d9f12f3
VS
126 win->Close();
127
128 return TRUE;
129}
130
131
132//-----------------------------------------------------------------------------
133// "configure_event"
134//-----------------------------------------------------------------------------
135
136static gint
7d9f12f3 137gtk_frame_configure_callback( GtkWidget *WXUNUSED(widget), GdkEventConfigure *WXUNUSED(event), wxTopLevelWindowGTK *win )
7d9f12f3
VS
138{
139 if (g_isIdle)
140 wxapp_install_idle_handler();
141
48f72114 142 if (!win->m_hasVMT || !win->IsShown())
7d9f12f3
VS
143 return FALSE;
144
7d9f12f3
VS
145 int x = 0;
146 int y = 0;
147 gdk_window_get_root_origin( win->m_widget->window, &x, &y );
148 win->m_x = x;
149 win->m_y = y;
7d9f12f3
VS
150
151 wxMoveEvent mevent( wxPoint(win->m_x,win->m_y), win->GetId() );
152 mevent.SetEventObject( win );
153 win->GetEventHandler()->ProcessEvent( mevent );
154
155 return FALSE;
156}
157
158//-----------------------------------------------------------------------------
159// "realize" from m_widget
160//-----------------------------------------------------------------------------
161
e1f14d22
RR
162// we cannot MWM hints and icons before the widget has been realized,
163// so we do this directly after realization
7d9f12f3
VS
164
165static void
6aeb6f2a
VZ
166gtk_frame_realized_callback( GtkWidget * WXUNUSED(widget),
167 wxTopLevelWindowGTK *win )
7d9f12f3
VS
168{
169 if (g_isIdle)
170 wxapp_install_idle_handler();
171
e1f14d22
RR
172 // All this is for Motif Window Manager "hints" and is supposed to be
173 // recognized by other WM as well. Not tested.
82c9f85c 174 gdk_window_set_decorations(win->m_widget->window,
f819b4a3 175 (GdkWMDecoration)win->m_gdkDecor);
82c9f85c 176 gdk_window_set_functions(win->m_widget->window,
f819b4a3 177 (GdkWMFunction)win->m_gdkFunc);
7d9f12f3 178
e1f14d22 179 // GTK's shrinking/growing policy
f819b4a3 180 if ((win->m_gdkFunc & GDK_FUNC_RESIZE) == 0)
7d9f12f3
VS
181 gtk_window_set_policy(GTK_WINDOW(win->m_widget), 0, 0, 1);
182 else
183 gtk_window_set_policy(GTK_WINDOW(win->m_widget), 1, 1, 1);
184
e1f14d22 185 // reset the icon
7efaed4d 186 wxIconBundle iconsOld = win->GetIcons();
6aeb6f2a 187 if ( iconsOld.GetIcon(-1).Ok() )
7d9f12f3 188 {
7d9f12f3 189 win->SetIcon( wxNullIcon );
7efaed4d 190 win->SetIcons( iconsOld );
7d9f12f3 191 }
7d9f12f3
VS
192}
193
194//-----------------------------------------------------------------------------
195// "map_event" from m_widget
196//-----------------------------------------------------------------------------
197
198static void
199gtk_frame_map_callback( GtkWidget * WXUNUSED(widget),
200 GdkEvent * WXUNUSED(event),
201 wxTopLevelWindow *win )
202{
203 win->SetIconizeState(FALSE);
204}
205
206//-----------------------------------------------------------------------------
207// "unmap_event" from m_widget
208//-----------------------------------------------------------------------------
209
210static void
211gtk_frame_unmap_callback( GtkWidget * WXUNUSED(widget),
212 GdkEvent * WXUNUSED(event),
213 wxTopLevelWindow *win )
214{
215 win->SetIconizeState(TRUE);
216}
217
218//-----------------------------------------------------------------------------
219// "expose_event" of m_client
220//-----------------------------------------------------------------------------
221
222static int gtk_window_expose_callback( GtkWidget *widget, GdkEventExpose *gdk_event, wxWindow *win )
223{
224 GtkPizza *pizza = GTK_PIZZA(widget);
225
90350682
VZ
226 gtk_paint_flat_box (win->m_widget->style,
227 pizza->bin_window, GTK_STATE_NORMAL,
228 GTK_SHADOW_NONE,
229 &gdk_event->area,
230 win->m_widget,
231 (char *)"base",
232 0, 0, -1, -1);
7d9f12f3 233
cba9ef7f 234 return FALSE;
7d9f12f3
VS
235}
236
237//-----------------------------------------------------------------------------
238// "draw" of m_client
239//-----------------------------------------------------------------------------
240
52d6235d 241#ifndef __WXGTK20__
7d9f12f3
VS
242
243static void gtk_window_draw_callback( GtkWidget *widget, GdkRectangle *rect, wxWindow *win )
244{
245 GtkPizza *pizza = GTK_PIZZA(widget);
246
90350682
VZ
247 gtk_paint_flat_box (win->m_widget->style,
248 pizza->bin_window, GTK_STATE_NORMAL,
249 GTK_SHADOW_NONE,
250 rect,
251 win->m_widget,
252 (char *)"base",
253 0, 0, -1, -1);
7d9f12f3
VS
254}
255
52d6235d
VZ
256#endif // GTK+ 1.x
257
7d9f12f3
VS
258// ----------------------------------------------------------------------------
259// wxTopLevelWindowGTK itself
260// ----------------------------------------------------------------------------
261
262//-----------------------------------------------------------------------------
263// InsertChild for wxTopLevelWindowGTK
264//-----------------------------------------------------------------------------
265
266/* Callback for wxTopLevelWindowGTK. This very strange beast has to be used because
267 * C++ has no virtual methods in a constructor. We have to emulate a
77ffb593 268 * virtual function here as wxWidgets requires different ways to insert
7d9f12f3
VS
269 * a child in container classes. */
270
271static void wxInsertChildInTopLevelWindow( wxTopLevelWindowGTK* parent, wxWindow* child )
272{
273 wxASSERT( GTK_IS_WIDGET(child->m_widget) );
274
275 if (!parent->m_insertInClientArea)
276 {
e1f14d22 277 // these are outside the client area
7d9f12f3
VS
278 wxTopLevelWindowGTK* frame = (wxTopLevelWindowGTK*) parent;
279 gtk_pizza_put( GTK_PIZZA(frame->m_mainWidget),
280 GTK_WIDGET(child->m_widget),
281 child->m_x,
282 child->m_y,
283 child->m_width,
284 child->m_height );
285 }
286 else
287 {
e1f14d22 288 // these are inside the client area
7d9f12f3
VS
289 gtk_pizza_put( GTK_PIZZA(parent->m_wxwindow),
290 GTK_WIDGET(child->m_widget),
e4b7b2b0
VS
291 child->m_x,
292 child->m_y,
7d9f12f3
VS
293 child->m_width,
294 child->m_height );
295 }
296
e1f14d22 297 // resize on OnInternalIdle
7d9f12f3
VS
298 parent->GtkUpdateSize();
299}
300
301// ----------------------------------------------------------------------------
302// wxTopLevelWindowGTK creation
303// ----------------------------------------------------------------------------
304
305void wxTopLevelWindowGTK::Init()
306{
307 m_sizeSet = FALSE;
308 m_miniEdge = 0;
309 m_miniTitle = 0;
310 m_mainWidget = (GtkWidget*) NULL;
311 m_insertInClientArea = TRUE;
7d9f12f3
VS
312 m_isIconized = FALSE;
313 m_fsIsShowing = FALSE;
314 m_themeEnabled = TRUE;
f819b4a3 315 m_gdkDecor = m_gdkFunc = 0;
5152b0e5 316 m_grabbed = FALSE;
7d9f12f3
VS
317}
318
319bool wxTopLevelWindowGTK::Create( wxWindow *parent,
f819b4a3
VS
320 wxWindowID id,
321 const wxString& title,
322 const wxPoint& pos,
323 const wxSize& sizeOrig,
324 long style,
325 const wxString &name )
7d9f12f3
VS
326{
327 // always create a frame of some reasonable, even if arbitrary, size (at
328 // least for MSW compatibility)
329 wxSize size = sizeOrig;
1111cedc 330 size.x = WidthDefault(size.x);
66202a7e 331 size.y = HeightDefault(size.y);
7d9f12f3
VS
332
333 wxTopLevelWindows.Append( this );
334
335 m_needParent = FALSE;
6aeb6f2a 336
7d9f12f3
VS
337 if (!PreCreation( parent, pos, size ) ||
338 !CreateBase( parent, id, pos, size, style, wxDefaultValidator, name ))
339 {
340 wxFAIL_MSG( wxT("wxTopLevelWindowGTK creation failed") );
341 return FALSE;
342 }
343
344 m_title = title;
345
346 m_insertCallback = (wxInsertChildFunction) wxInsertChildInTopLevelWindow;
347
63c5efa3
VS
348 // NB: m_widget may be !=NULL if it was created by derived class' Create,
349 // e.g. in wxTaskBarIconAreaGTK
350 if (m_widget == NULL)
351 {
352 GtkWindowType win_type = GTK_WINDOW_TOPLEVEL;
7d9f12f3 353
63c5efa3
VS
354 if (style & wxFRAME_TOOL_WINDOW)
355 win_type = GTK_WINDOW_POPUP;
82c9f85c 356
63c5efa3
VS
357 if (GetExtraStyle() & wxTOPLEVEL_EX_DIALOG)
358 {
359 // there is no more GTK_WINDOW_DIALOG in 2.0
9e691f46 360#ifdef __WXGTK20__
63c5efa3 361 win_type = GTK_WINDOW_TOPLEVEL;
9e691f46 362#else
63c5efa3 363 win_type = GTK_WINDOW_DIALOG;
9e691f46 364#endif
63c5efa3 365 }
7d9f12f3 366
63c5efa3
VS
367 m_widget = gtk_window_new( win_type );
368 }
7d9f12f3 369
50819679
JS
370 if (m_parent && (((GTK_IS_WINDOW(m_parent->m_widget)) &&
371 (GetExtraStyle() & wxTOPLEVEL_EX_DIALOG)) ||
372 (style & wxFRAME_FLOAT_ON_PARENT)))
7cd95599 373 {
7d9f12f3 374 gtk_window_set_transient_for( GTK_WINDOW(m_widget), GTK_WINDOW(m_parent->m_widget) );
7cd95599 375 }
7d9f12f3
VS
376
377 if (!name.IsEmpty())
fab591c5 378 gtk_window_set_wmclass( GTK_WINDOW(m_widget), wxGTK_CONV( name ), wxGTK_CONV( name ) );
7d9f12f3 379
fab591c5 380 gtk_window_set_title( GTK_WINDOW(m_widget), wxGTK_CONV( title ) );
7d9f12f3
VS
381 GTK_WIDGET_UNSET_FLAGS( m_widget, GTK_CAN_FOCUS );
382
383 gtk_signal_connect( GTK_OBJECT(m_widget), "delete_event",
384 GTK_SIGNAL_FUNC(gtk_frame_delete_callback), (gpointer)this );
385
e1f14d22 386 // m_mainWidget holds the toolbar, the menubar and the client area
7d9f12f3
VS
387 m_mainWidget = gtk_pizza_new();
388 gtk_widget_show( m_mainWidget );
389 GTK_WIDGET_UNSET_FLAGS( m_mainWidget, GTK_CAN_FOCUS );
390 gtk_container_add( GTK_CONTAINER(m_widget), m_mainWidget );
391
cba9ef7f
RR
392 if (m_miniEdge == 0) // wxMiniFrame has its own version.
393 {
394 // For m_mainWidget themes
395 gtk_signal_connect( GTK_OBJECT(m_mainWidget), "expose_event",
7d9f12f3 396 GTK_SIGNAL_FUNC(gtk_window_expose_callback), (gpointer)this );
4e5a4c69 397#ifndef __WXGTK20__
cba9ef7f 398 gtk_signal_connect( GTK_OBJECT(m_mainWidget), "draw",
7d9f12f3 399 GTK_SIGNAL_FUNC(gtk_window_draw_callback), (gpointer)this );
4e5a4c69 400#endif
cba9ef7f 401 }
7d9f12f3 402
e1f14d22 403 // m_wxwindow only represents the client area without toolbar and menubar
7d9f12f3
VS
404 m_wxwindow = gtk_pizza_new();
405 gtk_widget_show( m_wxwindow );
406 gtk_container_add( GTK_CONTAINER(m_mainWidget), m_wxwindow );
407
e1f14d22
RR
408 // we donm't allow the frame to get the focus as otherwise
409 // the frame will grab it at arbitrary focus changes
7d9f12f3
VS
410 GTK_WIDGET_UNSET_FLAGS( m_wxwindow, GTK_CAN_FOCUS );
411
412 if (m_parent) m_parent->AddChild( this );
413
e1f14d22 414 // the user resized the frame by dragging etc.
7d9f12f3
VS
415 gtk_signal_connect( GTK_OBJECT(m_widget), "size_allocate",
416 GTK_SIGNAL_FUNC(gtk_frame_size_callback), (gpointer)this );
417
418 PostCreation();
419
420 if ((m_x != -1) || (m_y != -1))
421 gtk_widget_set_uposition( m_widget, m_x, m_y );
6aeb6f2a 422
e1f14d22 423 gtk_window_set_default_size( GTK_WINDOW(m_widget), m_width, m_height );
7d9f12f3 424
e1f14d22
RR
425 // we cannot set MWM hints and icons before the widget has
426 // been realized, so we do this directly after realization
7d9f12f3
VS
427 gtk_signal_connect( GTK_OBJECT(m_widget), "realize",
428 GTK_SIGNAL_FUNC(gtk_frame_realized_callback), (gpointer) this );
429
e1f14d22 430 // the only way to get the window size is to connect to this event
7d9f12f3
VS
431 gtk_signal_connect( GTK_OBJECT(m_widget), "configure_event",
432 GTK_SIGNAL_FUNC(gtk_frame_configure_callback), (gpointer)this );
433
e1f14d22 434 // map and unmap for iconized state
7d9f12f3
VS
435 gtk_signal_connect( GTK_OBJECT(m_widget), "map_event",
436 GTK_SIGNAL_FUNC(gtk_frame_map_callback), (gpointer)this );
437 gtk_signal_connect( GTK_OBJECT(m_widget), "unmap_event",
438 GTK_SIGNAL_FUNC(gtk_frame_unmap_callback), (gpointer)this );
439
e1f14d22 440 // the only way to get the window size is to connect to this event
7d9f12f3
VS
441 gtk_signal_connect( GTK_OBJECT(m_widget), "configure_event",
442 GTK_SIGNAL_FUNC(gtk_frame_configure_callback), (gpointer)this );
443
e1f14d22 444 // disable native tab traversal
7d9f12f3
VS
445 gtk_signal_connect( GTK_OBJECT(m_widget), "focus",
446 GTK_SIGNAL_FUNC(gtk_frame_focus_callback), (gpointer)this );
447
e1f14d22 448 // decorations
f819b4a3
VS
449 if ((m_miniEdge > 0) || (style & wxSIMPLE_BORDER) || (style & wxNO_BORDER))
450 {
451 m_gdkDecor = 0;
452 m_gdkFunc = 0;
453 }
454 else
455 {
456 m_gdkDecor = (long) GDK_DECOR_BORDER;
457 m_gdkFunc = (long) GDK_FUNC_MOVE;
82c9f85c 458
f819b4a3 459 // All this is for Motif Window Manager "hints" and is supposed to be
e1f14d22 460 // recognized by other WMs as well.
f819b4a3 461 if ((style & wxCAPTION) != 0)
c3d8ee42 462 {
f819b4a3 463 m_gdkDecor |= GDK_DECOR_TITLE;
c3d8ee42 464 }
850c6ed4 465 if ((style & wxCLOSE_BOX) != 0)
f819b4a3
VS
466 {
467 m_gdkFunc |= GDK_FUNC_CLOSE;
c3d8ee42
VS
468 }
469 if ((style & wxSYSTEM_MENU) != 0)
470 {
f819b4a3
VS
471 m_gdkDecor |= GDK_DECOR_MENU;
472 }
473 if ((style & wxMINIMIZE_BOX) != 0)
474 {
475 m_gdkFunc |= GDK_FUNC_MINIMIZE;
476 m_gdkDecor |= GDK_DECOR_MINIMIZE;
477 }
478 if ((style & wxMAXIMIZE_BOX) != 0)
479 {
480 m_gdkFunc |= GDK_FUNC_MAXIMIZE;
481 m_gdkDecor |= GDK_DECOR_MAXIMIZE;
482 }
483 if ((style & wxRESIZE_BORDER) != 0)
484 {
485 m_gdkFunc |= GDK_FUNC_RESIZE;
486 m_gdkDecor |= GDK_DECOR_RESIZEH;
487 }
488 }
489
7d9f12f3
VS
490 return TRUE;
491}
492
493wxTopLevelWindowGTK::~wxTopLevelWindowGTK()
494{
5152b0e5
JS
495 if (m_grabbed)
496 {
83afe211 497 wxASSERT_MSG( FALSE, _T("Window still grabbed"));
5152b0e5
JS
498 RemoveGrab();
499 }
1cbee0b4 500
7d9f12f3 501 m_isBeingDeleted = TRUE;
6aeb6f2a 502
710968c3
VZ
503 // it may also be GtkScrolledWindow in the case of an MDI child
504 if (GTK_IS_WINDOW(m_widget))
505 {
506 gtk_window_set_focus( GTK_WINDOW(m_widget), NULL );
507 }
7d9f12f3
VS
508}
509
8a9650ea 510
8a9650ea 511
7d9f12f3
VS
512bool wxTopLevelWindowGTK::ShowFullScreen(bool show, long style )
513{
514 if (show == m_fsIsShowing) return FALSE; // return what?
515
516 m_fsIsShowing = show;
517
8166ab43 518 GdkWindow *window = m_widget->window;
1542ea39 519 wxX11FullScreenMethod method =
8166ab43
VS
520 wxGetFullScreenMethodX11((WXDisplay*)GDK_DISPLAY(),
521 (WXWindow)GDK_ROOT_WINDOW());
1542ea39 522
7d9f12f3
VS
523 if (show)
524 {
7d9f12f3
VS
525 m_fsSaveFlag = style;
526 GetPosition( &m_fsSaveFrame.x, &m_fsSaveFrame.y );
527 GetSize( &m_fsSaveFrame.width, &m_fsSaveFrame.height );
528
8a9650ea
RR
529 int screen_width,screen_height;
530 wxDisplaySize( &screen_width, &screen_height );
1cbee0b4 531
8a9650ea
RR
532 gint client_x, client_y, root_x, root_y;
533 gint width, height;
7d9f12f3 534
1cff04de 535 if (method != wxX11_FS_WMSPEC)
8166ab43
VS
536 {
537 // don't do it always, Metacity hates it
538 m_fsSaveGdkFunc = m_gdkFunc;
539 m_fsSaveGdkDecor = m_gdkDecor;
540 m_gdkFunc = m_gdkDecor = 0;
541 gdk_window_set_decorations(window, (GdkWMDecoration)0);
542 gdk_window_set_functions(window, (GdkWMFunction)0);
543 }
1542ea39 544
8a9650ea
RR
545 gdk_window_get_origin (m_widget->window, &root_x, &root_y);
546 gdk_window_get_geometry (m_widget->window, &client_x, &client_y,
547 &width, &height, NULL);
1cbee0b4 548
8a9650ea
RR
549 gdk_window_move_resize (m_widget->window, -client_x, -client_y,
550 screen_width + 1, screen_height + 1);
8166ab43
VS
551
552 wxSetFullScreenStateX11((WXDisplay*)GDK_DISPLAY(),
553 (WXWindow)GDK_ROOT_WINDOW(),
554 (WXWindow)GDK_WINDOW_XWINDOW(window),
555 show, &m_fsSaveFrame, method);
7d9f12f3
VS
556 }
557 else
558 {
1cff04de 559 if (method != wxX11_FS_WMSPEC)
8166ab43
VS
560 {
561 // don't do it always, Metacity hates it
562 m_gdkFunc = m_fsSaveGdkFunc;
563 m_gdkDecor = m_fsSaveGdkDecor;
564 gdk_window_set_decorations(window, (GdkWMDecoration)m_gdkDecor);
565 gdk_window_set_functions(window, (GdkWMFunction)m_gdkFunc);
566 }
1542ea39 567
8166ab43
VS
568 wxSetFullScreenStateX11((WXDisplay*)GDK_DISPLAY(),
569 (WXWindow)GDK_ROOT_WINDOW(),
570 (WXWindow)GDK_WINDOW_XWINDOW(window),
571 show, &m_fsSaveFrame, method);
1542ea39 572
8166ab43
VS
573 SetSize(m_fsSaveFrame.x, m_fsSaveFrame.y,
574 m_fsSaveFrame.width, m_fsSaveFrame.height);
7d9f12f3
VS
575 }
576
8166ab43 577
7d9f12f3
VS
578 return TRUE;
579}
580
581// ----------------------------------------------------------------------------
582// overridden wxWindow methods
583// ----------------------------------------------------------------------------
584
585bool wxTopLevelWindowGTK::Show( bool show )
586{
82b978d7 587 wxASSERT_MSG( (m_widget != NULL), wxT("invalid frame") );
7d9f12f3
VS
588
589 if (show && !m_sizeSet)
590 {
591 /* by calling GtkOnSize here, we don't have to call
592 either after showing the frame, which would entail
593 much ugly flicker or from within the size_allocate
594 handler, because GTK 1.1.X forbids that. */
595
596 GtkOnSize( m_x, m_y, m_width, m_height );
597 }
598
599 return wxWindow::Show( show );
600}
601
602void wxTopLevelWindowGTK::DoMoveWindow(int WXUNUSED(x), int WXUNUSED(y), int WXUNUSED(width), int WXUNUSED(height) )
603{
604 wxFAIL_MSG( wxT("DoMoveWindow called for wxTopLevelWindowGTK") );
605}
606
607void wxTopLevelWindowGTK::DoSetSize( int x, int y, int width, int height, int sizeFlags )
608{
82b978d7
RD
609 wxASSERT_MSG( (m_widget != NULL), wxT("invalid frame") );
610
e1f14d22 611 // this shouldn't happen: wxFrame, wxMDIParentFrame and wxMDIChildFrame have m_wxwindow
7d9f12f3
VS
612 wxASSERT_MSG( (m_wxwindow != NULL), wxT("invalid frame") );
613
e1f14d22 614 // avoid recursions
7d9f12f3
VS
615 if (m_resizing)
616 return;
617 m_resizing = TRUE;
618
619 int old_x = m_x;
620 int old_y = m_y;
621
622 int old_width = m_width;
623 int old_height = m_height;
624
625 if ((sizeFlags & wxSIZE_ALLOW_MINUS_ONE) == 0)
626 {
627 if (x != -1) m_x = x;
628 if (y != -1) m_y = y;
7d9f12f3
VS
629 }
630 else
631 {
632 m_x = x;
633 m_y = y;
7d9f12f3 634 }
d44c23ce
RR
635 if (width != -1) m_width = width;
636 if (height != -1) m_height = height;
7d9f12f3
VS
637
638/*
639 if ((sizeFlags & wxSIZE_AUTO_WIDTH) == wxSIZE_AUTO_WIDTH)
640 {
641 if (width == -1) m_width = 80;
642 }
643
644 if ((sizeFlags & wxSIZE_AUTO_HEIGHT) == wxSIZE_AUTO_HEIGHT)
645 {
646 if (height == -1) m_height = 26;
647 }
648*/
649
e7dda1ff
VS
650 int minWidth = GetMinWidth(),
651 minHeight = GetMinHeight(),
652 maxWidth = GetMaxWidth(),
653 maxHeight = GetMaxHeight();
654
62be94e1
RR
655#ifdef __WXGPE__
656 // GPE's window manager doesn't like size hints
657 // at all, esp. when the user has to use the
658 // virtual keyboard.
659 minWidth = -1;
660 minHeight = -1;
661 maxWidth = -1;
662 maxHeight = -1;
663#endif
ca06ee0d 664
e7dda1ff
VS
665 if ((minWidth != -1) && (m_width < minWidth)) m_width = minWidth;
666 if ((minHeight != -1) && (m_height < minHeight)) m_height = minHeight;
667 if ((maxWidth != -1) && (m_width > maxWidth)) m_width = maxWidth;
668 if ((maxHeight != -1) && (m_height > maxHeight)) m_height = maxHeight;
7d9f12f3
VS
669
670 if ((m_x != -1) || (m_y != -1))
671 {
672 if ((m_x != old_x) || (m_y != old_y))
673 {
674 gtk_widget_set_uposition( m_widget, m_x, m_y );
675 }
676 }
677
678 if ((m_width != old_width) || (m_height != old_height))
679 {
e1f14d22
RR
680 if (m_widget->window)
681 gdk_window_resize( m_widget->window, m_width, m_height );
682 else
683 gtk_window_set_default_size( GTK_WINDOW(m_widget), m_width, m_height );
7d9f12f3
VS
684
685 /* we set the size in GtkOnSize, i.e. mostly the actual resizing is
686 done either directly before the frame is shown or in idle time
687 so that different calls to SetSize() don't lead to flicker. */
688 m_sizeSet = FALSE;
689 }
690
691 m_resizing = FALSE;
692}
693
694void wxTopLevelWindowGTK::DoGetClientSize( int *width, int *height ) const
695{
82b978d7
RD
696 wxASSERT_MSG( (m_widget != NULL), wxT("invalid frame") );
697
7d9f12f3
VS
698 wxWindow::DoGetClientSize( width, height );
699 if (height)
700 {
e1f14d22 701 // mini edge
7d9f12f3
VS
702 *height -= m_miniEdge*2 + m_miniTitle;
703 }
704 if (width)
705 {
706 *width -= m_miniEdge*2;
707 }
708}
709
710void wxTopLevelWindowGTK::DoSetClientSize( int width, int height )
711{
82b978d7 712 wxASSERT_MSG( (m_widget != NULL), wxT("invalid frame") );
7d9f12f3 713
82c9f85c 714 DoSetSize(-1, -1,
7d9f12f3
VS
715 width + m_miniEdge*2, height + m_miniEdge*2 + m_miniTitle, 0);
716}
717
718void wxTopLevelWindowGTK::GtkOnSize( int WXUNUSED(x), int WXUNUSED(y),
82c9f85c 719 int width, int height )
7d9f12f3
VS
720{
721 // due to a bug in gtk, x,y are always 0
722 // m_x = x;
723 // m_y = y;
724
e1f14d22 725 // avoid recursions
7d9f12f3
VS
726 if (m_resizing) return;
727 m_resizing = TRUE;
728
729 if ( m_wxwindow == NULL ) return;
730
731 m_width = width;
732 m_height = height;
733
0d53fc34 734 /* wxMDIChildFrame derives from wxFrame but it _is_ a wxWindow as it uses
7d9f12f3 735 wxWindow::Create to create it's GTK equivalent. m_mainWidget is only
0d53fc34 736 set in wxFrame::Create so it is used to check what kind of frame we
7d9f12f3
VS
737 have here. if m_mainWidget is NULL it is a wxMDIChildFrame and so we
738 skip the part which handles m_frameMenuBar, m_frameToolBar and (most
739 importantly) m_mainWidget */
740
e7dda1ff
VS
741 int minWidth = GetMinWidth(),
742 minHeight = GetMinHeight(),
743 maxWidth = GetMaxWidth(),
744 maxHeight = GetMaxHeight();
745
62be94e1
RR
746#ifdef __WXGPE__
747 // GPE's window manager doesn't like size hints
748 // at all, esp. when the user has to use the
749 // virtual keyboard.
750 minWidth = -1;
751 minHeight = -1;
752 maxWidth = -1;
753 maxHeight = -1;
754#endif
ca06ee0d 755
e7dda1ff
VS
756 if ((minWidth != -1) && (m_width < minWidth)) m_width = minWidth;
757 if ((minHeight != -1) && (m_height < minHeight)) m_height = minHeight;
758 if ((maxWidth != -1) && (m_width > maxWidth)) m_width = maxWidth;
759 if ((maxHeight != -1) && (m_height > maxHeight)) m_height = maxHeight;
7d9f12f3
VS
760
761 if (m_mainWidget)
762 {
e1f14d22 763 // set size hints
801225c1
RL
764 gint flag = 0; // GDK_HINT_POS;
765 GdkGeometry geom;
766
e7dda1ff
VS
767 if ((minWidth != -1) || (minHeight != -1)) flag |= GDK_HINT_MIN_SIZE;
768 if ((maxWidth != -1) || (maxHeight != -1)) flag |= GDK_HINT_MAX_SIZE;
801225c1 769
e7dda1ff
VS
770 geom.min_width = minWidth;
771 geom.min_height = minHeight;
801225c1
RL
772
773 // Because of the way we set GDK_HINT_MAX_SIZE above, if either of
774 // maxHeight or maxWidth is set, we must set them both, else the
775 // remaining -1 will be taken literally.
776
777 // I'm certain this also happens elsewhere, and is the probable
778 // cause of other such things as:
779 // Gtk-WARNING **: gtk_widget_size_allocate():
780 // attempt to allocate widget with width 65535 and height 600
781 // but I don't have time to track them all now..
1cbee0b4 782 //
801225c1
RL
783 // Really we need to encapulate all this height/width business and
784 // stop any old method from ripping at the members directly and
785 // scattering -1's without regard for who might resolve them later.
786
787 geom.max_width = ( maxHeight == -1 ) ? maxWidth
788 : ( maxWidth == -1 ) ? wxGetDisplaySize().GetWidth()
789 : maxWidth ;
790
791 geom.max_height = ( maxWidth == -1 ) ? maxHeight // ( == -1 here )
792 : ( maxHeight == -1 ) ? wxGetDisplaySize().GetHeight()
793 : maxHeight ;
794
7d9f12f3
VS
795 gtk_window_set_geometry_hints( GTK_WINDOW(m_widget),
796 (GtkWidget*) NULL,
797 &geom,
798 (GdkWindowHints) flag );
799
800 /* I revert back to wxGTK's original behaviour. m_mainWidget holds the
801 * menubar, the toolbar and the client area, which is represented by
802 * m_wxwindow.
803 * this hurts in the eye, but I don't want to call SetSize()
804 * because I don't want to call any non-native functions here. */
805
806 int client_x = m_miniEdge;
807 int client_y = m_miniEdge + m_miniTitle;
808 int client_w = m_width - 2*m_miniEdge;
809 int client_h = m_height - 2*m_miniEdge - m_miniTitle;
801225c1 810
7d9f12f3
VS
811 gtk_pizza_set_size( GTK_PIZZA(m_mainWidget),
812 m_wxwindow,
813 client_x, client_y, client_w, client_h );
814 }
815 else
816 {
e1f14d22
RR
817 // If there is no m_mainWidget between m_widget and m_wxwindow there
818 // is no need to set the size or position of m_wxwindow.
7d9f12f3
VS
819 }
820
821 m_sizeSet = TRUE;
822
823 // send size event to frame
824 wxSizeEvent event( wxSize(m_width,m_height), GetId() );
825 event.SetEventObject( this );
826 GetEventHandler()->ProcessEvent( event );
827
828 m_resizing = FALSE;
829}
830
831void wxTopLevelWindowGTK::OnInternalIdle()
832{
833 if (!m_sizeSet && GTK_WIDGET_REALIZED(m_wxwindow))
834 {
835 GtkOnSize( m_x, m_y, m_width, m_height );
836
837 // we'll come back later
838 if (g_isIdle)
839 wxapp_install_idle_handler();
840 return;
841 }
842
6aeb6f2a
VZ
843 // set the focus if not done yet and if we can already do it
844 if ( GTK_WIDGET_REALIZED(m_wxwindow) )
845 {
cc06fe74
MB
846 if ( g_delayedFocus &&
847 wxGetTopLevelParent((wxWindow*)g_delayedFocus) == this )
6aeb6f2a 848 {
2b5f62a0
VZ
849 wxLogTrace(_T("focus"),
850 _T("Setting focus from wxTLW::OnIdle() to %s(%s)"),
851 g_delayedFocus->GetClassInfo()->GetClassName(),
852 g_delayedFocus->GetLabel().c_str());
853
6aeb6f2a
VZ
854 g_delayedFocus->SetFocus();
855 g_delayedFocus = NULL;
856 }
857 }
858
7d9f12f3
VS
859 wxWindow::OnInternalIdle();
860}
861
7d9f12f3
VS
862// ----------------------------------------------------------------------------
863// frame title/icon
864// ----------------------------------------------------------------------------
865
866void wxTopLevelWindowGTK::SetTitle( const wxString &title )
867{
82b978d7
RD
868 wxASSERT_MSG( (m_widget != NULL), wxT("invalid frame") );
869
7d9f12f3 870 m_title = title;
fab591c5 871 gtk_window_set_title( GTK_WINDOW(m_widget), wxGTK_CONV( title ) );
7d9f12f3
VS
872}
873
f618020a 874void wxTopLevelWindowGTK::DoSetIcon( const wxIcon &icon )
7d9f12f3 875{
f618020a 876 if ( !icon.Ok() )
7d9f12f3
VS
877 return;
878
879 if (!m_widget->window)
880 return;
881
882 wxMask *mask = icon.GetMask();
883 GdkBitmap *bm = (GdkBitmap *) NULL;
884 if (mask) bm = mask->GetBitmap();
885
886 gdk_window_set_icon( m_widget->window, (GdkWindow *) NULL, icon.GetPixmap(), bm );
887}
888
f618020a
MB
889void wxTopLevelWindowGTK::SetIcon( const wxIcon &icon )
890{
891 SetIcons( wxIconBundle( icon ) );
892}
893
894void wxTopLevelWindowGTK::SetIcons( const wxIconBundle &icons )
895{
82b978d7 896 wxASSERT_MSG( (m_widget != NULL), wxT("invalid frame") );
f618020a 897 GdkWindow* window = m_widget->window;
f618020a
MB
898
899 wxTopLevelWindowBase::SetIcons( icons );
900
901 DoSetIcon( icons.GetIcon( -1 ) );
52d6235d
VZ
902 if ( window )
903 {
7efaed4d
MB
904 wxSetIconsX11( (WXDisplay*)GDK_WINDOW_XDISPLAY( window ),
905 (WXWindow)GDK_WINDOW_XWINDOW( window ), icons );
52d6235d 906 }
f618020a
MB
907}
908
7d9f12f3
VS
909// ----------------------------------------------------------------------------
910// frame state: maximized/iconized/normal
911// ----------------------------------------------------------------------------
912
8805e155 913void wxTopLevelWindowGTK::Maximize(bool maximize)
7d9f12f3 914{
8805e155
RR
915#ifdef __WXGTK20__
916 if (maximize)
917 gtk_window_maximize( GTK_WINDOW( m_widget ) );
918 else
919 gtk_window_unmaximize( GTK_WINDOW( m_widget ) );
920#else
7d9f12f3 921 wxFAIL_MSG( _T("not implemented") );
8805e155 922#endif
7d9f12f3
VS
923}
924
925bool wxTopLevelWindowGTK::IsMaximized() const
926{
927 // wxFAIL_MSG( _T("not implemented") );
928
929 // This is an approximation
930 return FALSE;
931}
932
933void wxTopLevelWindowGTK::Restore()
934{
8805e155
RR
935#ifdef __GTK20__
936 // "Present" seems similar enough to "restore"
937 gtk_window_present( GTK_WINDOW( m_widget ) );
938#else
7d9f12f3 939 wxFAIL_MSG( _T("not implemented") );
8805e155 940#endif
7d9f12f3
VS
941}
942
943void wxTopLevelWindowGTK::Iconize( bool iconize )
944{
8805e155
RR
945#ifdef __WXGTK20__
946 if (iconize)
947 gtk_window_iconify( GTK_WINDOW( m_widget ) );
948 else
949 gtk_window_deiconify( GTK_WINDOW( m_widget ) );
950#else
7d9f12f3
VS
951 if (iconize)
952 {
953 GdkWindow *window = m_widget->window;
954
955 // you should do it later, for example from OnCreate() handler
956 wxCHECK_RET( window, _T("frame not created yet - can't iconize") );
957
958 XIconifyWindow( GDK_WINDOW_XDISPLAY( window ),
959 GDK_WINDOW_XWINDOW( window ),
960 DefaultScreen( GDK_DISPLAY() ) );
961 }
8805e155 962#endif
7d9f12f3
VS
963}
964
965bool wxTopLevelWindowGTK::IsIconized() const
966{
967 return m_isIconized;
968}
969
970void wxTopLevelWindowGTK::SetIconizeState(bool iconize)
971{
972 if ( iconize != m_isIconized )
973 {
974 m_isIconized = iconize;
975 (void)SendIconizeEvent(iconize);
976 }
977}
978
5152b0e5
JS
979void wxTopLevelWindowGTK::AddGrab()
980{
981 if (!m_grabbed)
982 {
983 m_grabbed = TRUE;
984 gtk_grab_add( m_widget );
985 gtk_main();
986 gtk_grab_remove( m_widget );
987 }
988}
989
990void wxTopLevelWindowGTK::RemoveGrab()
991{
992 if (m_grabbed)
993 {
994 gtk_main_quit();
995 m_grabbed = FALSE;
996 }
997}
801225c1 998
1542ea39
RD
999
1000// helper
1001static bool do_shape_combine_region(GdkWindow* window, const wxRegion& region)
1002{
1003 if (window)
1004 {
1005 if (region.IsEmpty())
1006 {
1007 gdk_window_shape_combine_mask(window, NULL, 0, 0);
1008 }
1009 else
1010 {
1011#ifdef __WXGTK20__
1012 gdk_window_shape_combine_region(window, region.GetRegion(), 0, 0);
1013#else
1014 wxBitmap bmp = region.ConvertToBitmap();
819451b6 1015 bmp.SetMask(new wxMask(bmp, *wxBLACK));
1542ea39
RD
1016 GdkBitmap* mask = bmp.GetMask()->GetBitmap();
1017 gdk_window_shape_combine_mask(window, mask, 0, 0);
1018#endif
1019 return TRUE;
1020 }
1021 }
1022 return FALSE;
1023}
1024
1025
1026bool wxTopLevelWindowGTK::SetShape(const wxRegion& region)
1027{
6a7e6411
RD
1028 wxCHECK_MSG( HasFlag(wxFRAME_SHAPED), FALSE,
1029 _T("Shaped windows must be created with the wxFRAME_SHAPED style."));
1030
1542ea39
RD
1031 GdkWindow *window = NULL;
1032 if (m_wxwindow)
1033 {
1034 window = GTK_PIZZA(m_wxwindow)->bin_window;
1035 do_shape_combine_region(window, region);
1036 }
1037 window = m_widget->window;
1038 return do_shape_combine_region(window, region);
1039}
1040
801225c1 1041// vi:sts=4:sw=4:et