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