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