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