]> git.saurik.com Git - wxWidgets.git/blame - src/gtk1/toplevel.cpp
New positioning code, eliminating a lot of extra, unnecessary methods
[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
641 if ((m_minWidth != -1) && (m_width < m_minWidth)) m_width = m_minWidth;
642 if ((m_minHeight != -1) && (m_height < m_minHeight)) m_height = m_minHeight;
643 if ((m_maxWidth != -1) && (m_width > m_maxWidth)) m_width = m_maxWidth;
644 if ((m_maxHeight != -1) && (m_height > m_maxHeight)) m_height = m_maxHeight;
645
646 if ((m_x != -1) || (m_y != -1))
647 {
648 if ((m_x != old_x) || (m_y != old_y))
649 {
650 gtk_widget_set_uposition( m_widget, m_x, m_y );
651 }
652 }
653
654 if ((m_width != old_width) || (m_height != old_height))
655 {
e1f14d22
RR
656 if (m_widget->window)
657 gdk_window_resize( m_widget->window, m_width, m_height );
658 else
659 gtk_window_set_default_size( GTK_WINDOW(m_widget), m_width, m_height );
7d9f12f3
VS
660
661 /* we set the size in GtkOnSize, i.e. mostly the actual resizing is
662 done either directly before the frame is shown or in idle time
663 so that different calls to SetSize() don't lead to flicker. */
664 m_sizeSet = FALSE;
665 }
666
667 m_resizing = FALSE;
668}
669
670void wxTopLevelWindowGTK::DoGetClientSize( int *width, int *height ) const
671{
672 wxASSERT_MSG( (m_widget != NULL), wxT("invalid frame") );
673
674 wxWindow::DoGetClientSize( width, height );
675 if (height)
676 {
e1f14d22 677 // mini edge
7d9f12f3
VS
678 *height -= m_miniEdge*2 + m_miniTitle;
679 }
680 if (width)
681 {
682 *width -= m_miniEdge*2;
683 }
684}
685
686void wxTopLevelWindowGTK::DoSetClientSize( int width, int height )
687{
688 wxASSERT_MSG( (m_widget != NULL), wxT("invalid frame") );
689
82c9f85c 690 DoSetSize(-1, -1,
7d9f12f3
VS
691 width + m_miniEdge*2, height + m_miniEdge*2 + m_miniTitle, 0);
692}
693
694void wxTopLevelWindowGTK::GtkOnSize( int WXUNUSED(x), int WXUNUSED(y),
82c9f85c 695 int width, int height )
7d9f12f3
VS
696{
697 // due to a bug in gtk, x,y are always 0
698 // m_x = x;
699 // m_y = y;
700
e1f14d22 701 // avoid recursions
7d9f12f3
VS
702 if (m_resizing) return;
703 m_resizing = TRUE;
704
705 if ( m_wxwindow == NULL ) return;
706
707 m_width = width;
708 m_height = height;
709
0d53fc34 710 /* wxMDIChildFrame derives from wxFrame but it _is_ a wxWindow as it uses
7d9f12f3 711 wxWindow::Create to create it's GTK equivalent. m_mainWidget is only
0d53fc34 712 set in wxFrame::Create so it is used to check what kind of frame we
7d9f12f3
VS
713 have here. if m_mainWidget is NULL it is a wxMDIChildFrame and so we
714 skip the part which handles m_frameMenuBar, m_frameToolBar and (most
715 importantly) m_mainWidget */
716
717 if ((m_minWidth != -1) && (m_width < m_minWidth)) m_width = m_minWidth;
718 if ((m_minHeight != -1) && (m_height < m_minHeight)) m_height = m_minHeight;
719 if ((m_maxWidth != -1) && (m_width > m_maxWidth)) m_width = m_maxWidth;
720 if ((m_maxHeight != -1) && (m_height > m_maxHeight)) m_height = m_maxHeight;
721
722 if (m_mainWidget)
723 {
e1f14d22 724 // set size hints
7d9f12f3
VS
725 gint flag = 0; // GDK_HINT_POS;
726 if ((m_minWidth != -1) || (m_minHeight != -1)) flag |= GDK_HINT_MIN_SIZE;
727 if ((m_maxWidth != -1) || (m_maxHeight != -1)) flag |= GDK_HINT_MAX_SIZE;
728 GdkGeometry geom;
729 geom.min_width = m_minWidth;
730 geom.min_height = m_minHeight;
731 geom.max_width = m_maxWidth;
732 geom.max_height = m_maxHeight;
733 gtk_window_set_geometry_hints( GTK_WINDOW(m_widget),
734 (GtkWidget*) NULL,
735 &geom,
736 (GdkWindowHints) flag );
737
738 /* I revert back to wxGTK's original behaviour. m_mainWidget holds the
739 * menubar, the toolbar and the client area, which is represented by
740 * m_wxwindow.
741 * this hurts in the eye, but I don't want to call SetSize()
742 * because I don't want to call any non-native functions here. */
743
744 int client_x = m_miniEdge;
745 int client_y = m_miniEdge + m_miniTitle;
746 int client_w = m_width - 2*m_miniEdge;
747 int client_h = m_height - 2*m_miniEdge - m_miniTitle;
748 gtk_pizza_set_size( GTK_PIZZA(m_mainWidget),
749 m_wxwindow,
750 client_x, client_y, client_w, client_h );
751 }
752 else
753 {
e1f14d22
RR
754 // If there is no m_mainWidget between m_widget and m_wxwindow there
755 // is no need to set the size or position of m_wxwindow.
7d9f12f3
VS
756 }
757
758 m_sizeSet = TRUE;
759
760 // send size event to frame
761 wxSizeEvent event( wxSize(m_width,m_height), GetId() );
762 event.SetEventObject( this );
763 GetEventHandler()->ProcessEvent( event );
764
765 m_resizing = FALSE;
766}
767
768void wxTopLevelWindowGTK::OnInternalIdle()
769{
770 if (!m_sizeSet && GTK_WIDGET_REALIZED(m_wxwindow))
771 {
772 GtkOnSize( m_x, m_y, m_width, m_height );
773
774 // we'll come back later
775 if (g_isIdle)
776 wxapp_install_idle_handler();
777 return;
778 }
779
780 wxWindow::OnInternalIdle();
781}
782
783
784// ----------------------------------------------------------------------------
785// frame title/icon
786// ----------------------------------------------------------------------------
787
788void wxTopLevelWindowGTK::SetTitle( const wxString &title )
789{
790 wxASSERT_MSG( (m_widget != NULL), wxT("invalid frame") );
791
792 m_title = title;
793 gtk_window_set_title( GTK_WINDOW(m_widget), title.mbc_str() );
794}
795
796void wxTopLevelWindowGTK::SetIcon( const wxIcon &icon )
797{
798 wxASSERT_MSG( (m_widget != NULL), wxT("invalid frame") );
799
800 wxTopLevelWindowBase::SetIcon(icon);
801
802 if ( !m_icon.Ok() )
803 return;
804
805 if (!m_widget->window)
806 return;
807
808 wxMask *mask = icon.GetMask();
809 GdkBitmap *bm = (GdkBitmap *) NULL;
810 if (mask) bm = mask->GetBitmap();
811
812 gdk_window_set_icon( m_widget->window, (GdkWindow *) NULL, icon.GetPixmap(), bm );
813}
814
815// ----------------------------------------------------------------------------
816// frame state: maximized/iconized/normal
817// ----------------------------------------------------------------------------
818
819void wxTopLevelWindowGTK::Maximize(bool WXUNUSED(maximize))
820{
821 wxFAIL_MSG( _T("not implemented") );
822}
823
824bool wxTopLevelWindowGTK::IsMaximized() const
825{
826 // wxFAIL_MSG( _T("not implemented") );
827
828 // This is an approximation
829 return FALSE;
830}
831
832void wxTopLevelWindowGTK::Restore()
833{
834 wxFAIL_MSG( _T("not implemented") );
835}
836
837void wxTopLevelWindowGTK::Iconize( bool iconize )
838{
839 if (iconize)
840 {
841 GdkWindow *window = m_widget->window;
842
843 // you should do it later, for example from OnCreate() handler
844 wxCHECK_RET( window, _T("frame not created yet - can't iconize") );
845
846 XIconifyWindow( GDK_WINDOW_XDISPLAY( window ),
847 GDK_WINDOW_XWINDOW( window ),
848 DefaultScreen( GDK_DISPLAY() ) );
849 }
850}
851
852bool wxTopLevelWindowGTK::IsIconized() const
853{
854 return m_isIconized;
855}
856
857void wxTopLevelWindowGTK::SetIconizeState(bool iconize)
858{
859 if ( iconize != m_isIconized )
860 {
861 m_isIconized = iconize;
862 (void)SendIconizeEvent(iconize);
863 }
864}
865