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