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