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