]> git.saurik.com Git - wxWidgets.git/blame - src/gtk/toplevel.cpp
better use strncpy() than strncat() with uninitialized buffer
[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
7cd95599 365 if (m_parent && (GTK_IS_WINDOW(m_parent->m_widget)) &&
2c990ec0 366 (GetExtraStyle() & wxTOPLEVEL_EX_DIALOG))
7cd95599 367 {
7d9f12f3 368 gtk_window_set_transient_for( GTK_WINDOW(m_widget), GTK_WINDOW(m_parent->m_widget) );
7cd95599 369 }
7d9f12f3
VS
370
371 if (!name.IsEmpty())
fab591c5 372 gtk_window_set_wmclass( GTK_WINDOW(m_widget), wxGTK_CONV( name ), wxGTK_CONV( name ) );
7d9f12f3 373
fab591c5 374 gtk_window_set_title( GTK_WINDOW(m_widget), wxGTK_CONV( title ) );
7d9f12f3
VS
375 GTK_WIDGET_UNSET_FLAGS( m_widget, GTK_CAN_FOCUS );
376
377 gtk_signal_connect( GTK_OBJECT(m_widget), "delete_event",
378 GTK_SIGNAL_FUNC(gtk_frame_delete_callback), (gpointer)this );
379
e1f14d22 380 // m_mainWidget holds the toolbar, the menubar and the client area
7d9f12f3
VS
381 m_mainWidget = gtk_pizza_new();
382 gtk_widget_show( m_mainWidget );
383 GTK_WIDGET_UNSET_FLAGS( m_mainWidget, GTK_CAN_FOCUS );
384 gtk_container_add( GTK_CONTAINER(m_widget), m_mainWidget );
385
e1f14d22 386 // for m_mainWidget themes
7d9f12f3
VS
387 gtk_signal_connect( GTK_OBJECT(m_mainWidget), "expose_event",
388 GTK_SIGNAL_FUNC(gtk_window_expose_callback), (gpointer)this );
4e5a4c69 389#ifndef __WXGTK20__
7d9f12f3
VS
390 gtk_signal_connect( GTK_OBJECT(m_mainWidget), "draw",
391 GTK_SIGNAL_FUNC(gtk_window_draw_callback), (gpointer)this );
4e5a4c69 392#endif
7d9f12f3 393
e1f14d22 394 // m_wxwindow only represents the client area without toolbar and menubar
7d9f12f3
VS
395 m_wxwindow = gtk_pizza_new();
396 gtk_widget_show( m_wxwindow );
397 gtk_container_add( GTK_CONTAINER(m_mainWidget), m_wxwindow );
398
e1f14d22
RR
399 // we donm't allow the frame to get the focus as otherwise
400 // the frame will grab it at arbitrary focus changes
7d9f12f3
VS
401 GTK_WIDGET_UNSET_FLAGS( m_wxwindow, GTK_CAN_FOCUS );
402
403 if (m_parent) m_parent->AddChild( this );
404
e1f14d22 405 // the user resized the frame by dragging etc.
7d9f12f3
VS
406 gtk_signal_connect( GTK_OBJECT(m_widget), "size_allocate",
407 GTK_SIGNAL_FUNC(gtk_frame_size_callback), (gpointer)this );
408
409 PostCreation();
410
411 if ((m_x != -1) || (m_y != -1))
412 gtk_widget_set_uposition( m_widget, m_x, m_y );
6aeb6f2a 413
e1f14d22 414 gtk_window_set_default_size( GTK_WINDOW(m_widget), m_width, m_height );
7d9f12f3 415
e1f14d22
RR
416 // we cannot set MWM hints and icons before the widget has
417 // been realized, so we do this directly after realization
7d9f12f3
VS
418 gtk_signal_connect( GTK_OBJECT(m_widget), "realize",
419 GTK_SIGNAL_FUNC(gtk_frame_realized_callback), (gpointer) this );
420
e1f14d22 421 // the only way to get the window size is to connect to this event
7d9f12f3
VS
422 gtk_signal_connect( GTK_OBJECT(m_widget), "configure_event",
423 GTK_SIGNAL_FUNC(gtk_frame_configure_callback), (gpointer)this );
424
e1f14d22 425 // map and unmap for iconized state
7d9f12f3
VS
426 gtk_signal_connect( GTK_OBJECT(m_widget), "map_event",
427 GTK_SIGNAL_FUNC(gtk_frame_map_callback), (gpointer)this );
428 gtk_signal_connect( GTK_OBJECT(m_widget), "unmap_event",
429 GTK_SIGNAL_FUNC(gtk_frame_unmap_callback), (gpointer)this );
430
e1f14d22 431 // the only way to get the window size is to connect to this event
7d9f12f3
VS
432 gtk_signal_connect( GTK_OBJECT(m_widget), "configure_event",
433 GTK_SIGNAL_FUNC(gtk_frame_configure_callback), (gpointer)this );
434
e1f14d22 435 // disable native tab traversal
7d9f12f3
VS
436 gtk_signal_connect( GTK_OBJECT(m_widget), "focus",
437 GTK_SIGNAL_FUNC(gtk_frame_focus_callback), (gpointer)this );
438
e1f14d22 439 // decorations
f819b4a3
VS
440 if ((m_miniEdge > 0) || (style & wxSIMPLE_BORDER) || (style & wxNO_BORDER))
441 {
442 m_gdkDecor = 0;
443 m_gdkFunc = 0;
444 }
445 else
446 {
447 m_gdkDecor = (long) GDK_DECOR_BORDER;
448 m_gdkFunc = (long) GDK_FUNC_MOVE;
82c9f85c 449
f819b4a3 450 // All this is for Motif Window Manager "hints" and is supposed to be
e1f14d22 451 // recognized by other WMs as well.
f819b4a3
VS
452 if ((style & wxCAPTION) != 0)
453 m_gdkDecor |= GDK_DECOR_TITLE;
454 if ((style & wxSYSTEM_MENU) != 0)
455 {
456 m_gdkFunc |= GDK_FUNC_CLOSE;
457 m_gdkDecor |= GDK_DECOR_MENU;
458 }
459 if ((style & wxMINIMIZE_BOX) != 0)
460 {
461 m_gdkFunc |= GDK_FUNC_MINIMIZE;
462 m_gdkDecor |= GDK_DECOR_MINIMIZE;
463 }
464 if ((style & wxMAXIMIZE_BOX) != 0)
465 {
466 m_gdkFunc |= GDK_FUNC_MAXIMIZE;
467 m_gdkDecor |= GDK_DECOR_MAXIMIZE;
468 }
469 if ((style & wxRESIZE_BORDER) != 0)
470 {
471 m_gdkFunc |= GDK_FUNC_RESIZE;
472 m_gdkDecor |= GDK_DECOR_RESIZEH;
473 }
474 }
475
7d9f12f3
VS
476 return TRUE;
477}
478
479wxTopLevelWindowGTK::~wxTopLevelWindowGTK()
480{
5152b0e5
JS
481 if (m_grabbed)
482 {
483 wxASSERT_MSG( FALSE, "Window still grabbed");
484 RemoveGrab();
485 }
486
7d9f12f3 487 m_isBeingDeleted = TRUE;
6aeb6f2a 488
710968c3
VZ
489 // it may also be GtkScrolledWindow in the case of an MDI child
490 if (GTK_IS_WINDOW(m_widget))
491 {
492 gtk_window_set_focus( GTK_WINDOW(m_widget), NULL );
493 }
7d9f12f3
VS
494
495 wxTopLevelWindows.DeleteObject( this );
496
497 if (wxTheApp->GetTopWindow() == this)
498 wxTheApp->SetTopWindow( (wxWindow*) NULL );
499
500 if ((wxTopLevelWindows.Number() == 0) &&
501 (wxTheApp->GetExitOnFrameDelete()))
502 {
503 wxTheApp->ExitMainLoop();
504 }
505}
506
8a9650ea
RR
507
508// X11 ICCCM values for window layers
509#define WIN_LAYER_NORMAL 4
510#define WIN_LAYER_ABOVE_DOCK 10
511
512// X11 window manager property name
513#define XA_WIN_LAYER "_WIN_LAYER"
514
515// X11 window manager property name atom
516static Atom gs_XA_WIN_LAYER = 0;
517
518
519static void wx_win_hints_set_layer(GtkWidget *window, int layer)
520{
fab591c5
RR
521#ifndef __WXGTK20__
522 XEvent xev;
523 GdkWindowPrivate *priv;
524 gint prev_error;
8a9650ea 525
fab591c5
RR
526 prev_error = gdk_error_warnings;
527 gdk_error_warnings = 0;
528 priv = (GdkWindowPrivate*)(GTK_WIDGET(window)->window);
8a9650ea 529
fab591c5 530 if (GTK_WIDGET_MAPPED(window))
8a9650ea 531 {
fab591c5
RR
532 xev.type = ClientMessage;
533 xev.xclient.type = ClientMessage;
534 xev.xclient.window = priv->xwindow;
535 xev.xclient.message_type = gs_XA_WIN_LAYER;
536 xev.xclient.format = 32;
537 xev.xclient.data.l[0] = (long)layer;
538 xev.xclient.data.l[1] = gdk_time_get();
8a9650ea 539
fab591c5
RR
540 XSendEvent(GDK_DISPLAY(), GDK_ROOT_WINDOW(), False,
541 SubstructureNotifyMask, (XEvent*) &xev);
8a9650ea 542 }
fab591c5 543 else
8a9650ea 544 {
fab591c5 545 long data[1];
8a9650ea 546
fab591c5
RR
547 data[0] = layer;
548 XChangeProperty(GDK_DISPLAY(), priv->xwindow, gs_XA_WIN_LAYER,
549 XA_CARDINAL, 32, PropModeReplace, (unsigned char *)data, 1);
8a9650ea 550 }
fab591c5
RR
551 gdk_error_warnings = prev_error;
552#endif
8a9650ea
RR
553}
554
7d9f12f3
VS
555bool wxTopLevelWindowGTK::ShowFullScreen(bool show, long style )
556{
557 if (show == m_fsIsShowing) return FALSE; // return what?
558
8a9650ea
RR
559 if (gs_XA_WIN_LAYER == 0)
560 {
561 // Initialose X11 Atom only once
562 gs_XA_WIN_LAYER = XInternAtom( GDK_DISPLAY(), XA_WIN_LAYER, False );
563 }
564
7d9f12f3
VS
565 m_fsIsShowing = show;
566
567 if (show)
568 {
82f2d919
VS
569 m_fsSaveGdkFunc = m_gdkFunc;
570 m_fsSaveGdkDecor = m_gdkDecor;
7d9f12f3
VS
571 m_fsSaveFlag = style;
572 GetPosition( &m_fsSaveFrame.x, &m_fsSaveFrame.y );
573 GetSize( &m_fsSaveFrame.width, &m_fsSaveFrame.height );
574
8a9650ea
RR
575 int screen_width,screen_height;
576 wxDisplaySize( &screen_width, &screen_height );
577
578 gint client_x, client_y, root_x, root_y;
579 gint width, height;
7d9f12f3 580
8a9650ea
RR
581 gdk_window_get_origin (m_widget->window, &root_x, &root_y);
582 gdk_window_get_geometry (m_widget->window, &client_x, &client_y,
583 &width, &height, NULL);
584
585 wx_win_hints_set_layer( m_widget, WIN_LAYER_ABOVE_DOCK );
7d9f12f3 586
8a9650ea
RR
587 gdk_window_move_resize (m_widget->window, -client_x, -client_y,
588 screen_width + 1, screen_height + 1);
7d9f12f3
VS
589 }
590 else
591 {
8a9650ea
RR
592 wx_win_hints_set_layer( m_widget, WIN_LAYER_NORMAL );
593
7d9f12f3 594 SetSize( m_fsSaveFrame.x, m_fsSaveFrame.y, m_fsSaveFrame.width, m_fsSaveFrame.height );
7d9f12f3
VS
595 }
596
597 return TRUE;
598}
599
600// ----------------------------------------------------------------------------
601// overridden wxWindow methods
602// ----------------------------------------------------------------------------
603
604bool wxTopLevelWindowGTK::Show( bool show )
605{
606 wxASSERT_MSG( (m_widget != NULL), wxT("invalid frame") );
607
608 if (show && !m_sizeSet)
609 {
610 /* by calling GtkOnSize here, we don't have to call
611 either after showing the frame, which would entail
612 much ugly flicker or from within the size_allocate
613 handler, because GTK 1.1.X forbids that. */
614
615 GtkOnSize( m_x, m_y, m_width, m_height );
616 }
617
618 return wxWindow::Show( show );
619}
620
621void wxTopLevelWindowGTK::DoMoveWindow(int WXUNUSED(x), int WXUNUSED(y), int WXUNUSED(width), int WXUNUSED(height) )
622{
623 wxFAIL_MSG( wxT("DoMoveWindow called for wxTopLevelWindowGTK") );
624}
625
626void wxTopLevelWindowGTK::DoSetSize( int x, int y, int width, int height, int sizeFlags )
627{
628 wxASSERT_MSG( (m_widget != NULL), wxT("invalid frame") );
629
e1f14d22 630 // this shouldn't happen: wxFrame, wxMDIParentFrame and wxMDIChildFrame have m_wxwindow
7d9f12f3
VS
631 wxASSERT_MSG( (m_wxwindow != NULL), wxT("invalid frame") );
632
e1f14d22 633 // avoid recursions
7d9f12f3
VS
634 if (m_resizing)
635 return;
636 m_resizing = TRUE;
637
638 int old_x = m_x;
639 int old_y = m_y;
640
641 int old_width = m_width;
642 int old_height = m_height;
643
644 if ((sizeFlags & wxSIZE_ALLOW_MINUS_ONE) == 0)
645 {
646 if (x != -1) m_x = x;
647 if (y != -1) m_y = y;
7d9f12f3
VS
648 }
649 else
650 {
651 m_x = x;
652 m_y = y;
7d9f12f3 653 }
d44c23ce
RR
654 if (width != -1) m_width = width;
655 if (height != -1) m_height = height;
7d9f12f3
VS
656
657/*
658 if ((sizeFlags & wxSIZE_AUTO_WIDTH) == wxSIZE_AUTO_WIDTH)
659 {
660 if (width == -1) m_width = 80;
661 }
662
663 if ((sizeFlags & wxSIZE_AUTO_HEIGHT) == wxSIZE_AUTO_HEIGHT)
664 {
665 if (height == -1) m_height = 26;
666 }
667*/
668
e7dda1ff
VS
669 int minWidth = GetMinWidth(),
670 minHeight = GetMinHeight(),
671 maxWidth = GetMaxWidth(),
672 maxHeight = GetMaxHeight();
673
674 if ((minWidth != -1) && (m_width < minWidth)) m_width = minWidth;
675 if ((minHeight != -1) && (m_height < minHeight)) m_height = minHeight;
676 if ((maxWidth != -1) && (m_width > maxWidth)) m_width = maxWidth;
677 if ((maxHeight != -1) && (m_height > maxHeight)) m_height = maxHeight;
7d9f12f3
VS
678
679 if ((m_x != -1) || (m_y != -1))
680 {
681 if ((m_x != old_x) || (m_y != old_y))
682 {
683 gtk_widget_set_uposition( m_widget, m_x, m_y );
684 }
685 }
686
687 if ((m_width != old_width) || (m_height != old_height))
688 {
e1f14d22
RR
689 if (m_widget->window)
690 gdk_window_resize( m_widget->window, m_width, m_height );
691 else
692 gtk_window_set_default_size( GTK_WINDOW(m_widget), m_width, m_height );
7d9f12f3
VS
693
694 /* we set the size in GtkOnSize, i.e. mostly the actual resizing is
695 done either directly before the frame is shown or in idle time
696 so that different calls to SetSize() don't lead to flicker. */
697 m_sizeSet = FALSE;
698 }
699
700 m_resizing = FALSE;
701}
702
703void wxTopLevelWindowGTK::DoGetClientSize( int *width, int *height ) const
704{
705 wxASSERT_MSG( (m_widget != NULL), wxT("invalid frame") );
706
707 wxWindow::DoGetClientSize( width, height );
708 if (height)
709 {
e1f14d22 710 // mini edge
7d9f12f3
VS
711 *height -= m_miniEdge*2 + m_miniTitle;
712 }
713 if (width)
714 {
715 *width -= m_miniEdge*2;
716 }
717}
718
719void wxTopLevelWindowGTK::DoSetClientSize( int width, int height )
720{
721 wxASSERT_MSG( (m_widget != NULL), wxT("invalid frame") );
722
82c9f85c 723 DoSetSize(-1, -1,
7d9f12f3
VS
724 width + m_miniEdge*2, height + m_miniEdge*2 + m_miniTitle, 0);
725}
726
727void wxTopLevelWindowGTK::GtkOnSize( int WXUNUSED(x), int WXUNUSED(y),
82c9f85c 728 int width, int height )
7d9f12f3
VS
729{
730 // due to a bug in gtk, x,y are always 0
731 // m_x = x;
732 // m_y = y;
733
e1f14d22 734 // avoid recursions
7d9f12f3
VS
735 if (m_resizing) return;
736 m_resizing = TRUE;
737
738 if ( m_wxwindow == NULL ) return;
739
740 m_width = width;
741 m_height = height;
742
0d53fc34 743 /* wxMDIChildFrame derives from wxFrame but it _is_ a wxWindow as it uses
7d9f12f3 744 wxWindow::Create to create it's GTK equivalent. m_mainWidget is only
0d53fc34 745 set in wxFrame::Create so it is used to check what kind of frame we
7d9f12f3
VS
746 have here. if m_mainWidget is NULL it is a wxMDIChildFrame and so we
747 skip the part which handles m_frameMenuBar, m_frameToolBar and (most
748 importantly) m_mainWidget */
749
e7dda1ff
VS
750 int minWidth = GetMinWidth(),
751 minHeight = GetMinHeight(),
752 maxWidth = GetMaxWidth(),
753 maxHeight = GetMaxHeight();
754
755 if ((minWidth != -1) && (m_width < minWidth)) m_width = minWidth;
756 if ((minHeight != -1) && (m_height < minHeight)) m_height = minHeight;
757 if ((maxWidth != -1) && (m_width > maxWidth)) m_width = maxWidth;
758 if ((maxHeight != -1) && (m_height > maxHeight)) m_height = maxHeight;
7d9f12f3
VS
759
760 if (m_mainWidget)
761 {
e1f14d22 762 // set size hints
801225c1
RL
763 gint flag = 0; // GDK_HINT_POS;
764 GdkGeometry geom;
765
e7dda1ff
VS
766 if ((minWidth != -1) || (minHeight != -1)) flag |= GDK_HINT_MIN_SIZE;
767 if ((maxWidth != -1) || (maxHeight != -1)) flag |= GDK_HINT_MAX_SIZE;
801225c1 768
e7dda1ff
VS
769 geom.min_width = minWidth;
770 geom.min_height = minHeight;
801225c1
RL
771
772 // Because of the way we set GDK_HINT_MAX_SIZE above, if either of
773 // maxHeight or maxWidth is set, we must set them both, else the
774 // remaining -1 will be taken literally.
775
776 // I'm certain this also happens elsewhere, and is the probable
777 // cause of other such things as:
778 // Gtk-WARNING **: gtk_widget_size_allocate():
779 // attempt to allocate widget with width 65535 and height 600
780 // but I don't have time to track them all now..
781 //
782 // Really we need to encapulate all this height/width business and
783 // stop any old method from ripping at the members directly and
784 // scattering -1's without regard for who might resolve them later.
785
786 geom.max_width = ( maxHeight == -1 ) ? maxWidth
787 : ( maxWidth == -1 ) ? wxGetDisplaySize().GetWidth()
788 : maxWidth ;
789
790 geom.max_height = ( maxWidth == -1 ) ? maxHeight // ( == -1 here )
791 : ( maxHeight == -1 ) ? wxGetDisplaySize().GetHeight()
792 : maxHeight ;
793
7d9f12f3
VS
794 gtk_window_set_geometry_hints( GTK_WINDOW(m_widget),
795 (GtkWidget*) NULL,
796 &geom,
797 (GdkWindowHints) flag );
798
799 /* I revert back to wxGTK's original behaviour. m_mainWidget holds the
800 * menubar, the toolbar and the client area, which is represented by
801 * m_wxwindow.
802 * this hurts in the eye, but I don't want to call SetSize()
803 * because I don't want to call any non-native functions here. */
804
805 int client_x = m_miniEdge;
806 int client_y = m_miniEdge + m_miniTitle;
807 int client_w = m_width - 2*m_miniEdge;
808 int client_h = m_height - 2*m_miniEdge - m_miniTitle;
801225c1 809
7d9f12f3
VS
810 gtk_pizza_set_size( GTK_PIZZA(m_mainWidget),
811 m_wxwindow,
812 client_x, client_y, client_w, client_h );
813 }
814 else
815 {
e1f14d22
RR
816 // If there is no m_mainWidget between m_widget and m_wxwindow there
817 // is no need to set the size or position of m_wxwindow.
7d9f12f3
VS
818 }
819
820 m_sizeSet = TRUE;
821
822 // send size event to frame
823 wxSizeEvent event( wxSize(m_width,m_height), GetId() );
824 event.SetEventObject( this );
825 GetEventHandler()->ProcessEvent( event );
826
827 m_resizing = FALSE;
828}
829
830void wxTopLevelWindowGTK::OnInternalIdle()
831{
832 if (!m_sizeSet && GTK_WIDGET_REALIZED(m_wxwindow))
833 {
834 GtkOnSize( m_x, m_y, m_width, m_height );
835
836 // we'll come back later
837 if (g_isIdle)
838 wxapp_install_idle_handler();
839 return;
840 }
841
6aeb6f2a
VZ
842 // set the focus if not done yet and if we can already do it
843 if ( GTK_WIDGET_REALIZED(m_wxwindow) )
844 {
cc06fe74
MB
845 if ( g_delayedFocus &&
846 wxGetTopLevelParent((wxWindow*)g_delayedFocus) == this )
6aeb6f2a
VZ
847 {
848 g_delayedFocus->SetFocus();
849 g_delayedFocus = NULL;
850 }
851 }
852
7d9f12f3
VS
853 wxWindow::OnInternalIdle();
854}
855
7d9f12f3
VS
856// ----------------------------------------------------------------------------
857// frame title/icon
858// ----------------------------------------------------------------------------
859
860void wxTopLevelWindowGTK::SetTitle( const wxString &title )
861{
862 wxASSERT_MSG( (m_widget != NULL), wxT("invalid frame") );
863
864 m_title = title;
fab591c5 865 gtk_window_set_title( GTK_WINDOW(m_widget), wxGTK_CONV( title ) );
7d9f12f3
VS
866}
867
f618020a 868void wxTopLevelWindowGTK::DoSetIcon( const wxIcon &icon )
7d9f12f3 869{
f618020a 870 if ( !icon.Ok() )
7d9f12f3
VS
871 return;
872
873 if (!m_widget->window)
874 return;
875
876 wxMask *mask = icon.GetMask();
877 GdkBitmap *bm = (GdkBitmap *) NULL;
878 if (mask) bm = mask->GetBitmap();
879
880 gdk_window_set_icon( m_widget->window, (GdkWindow *) NULL, icon.GetPixmap(), bm );
881}
882
f618020a
MB
883void wxTopLevelWindowGTK::SetIcon( const wxIcon &icon )
884{
885 SetIcons( wxIconBundle( icon ) );
886}
887
888void wxTopLevelWindowGTK::SetIcons( const wxIconBundle &icons )
889{
890 wxASSERT_MSG( (m_widget != NULL), wxT("invalid frame") );
891 GdkWindow* window = m_widget->window;
f618020a
MB
892
893 wxTopLevelWindowBase::SetIcons( icons );
894
895 DoSetIcon( icons.GetIcon( -1 ) );
52d6235d
VZ
896 if ( window )
897 {
7efaed4d
MB
898 wxSetIconsX11( (WXDisplay*)GDK_WINDOW_XDISPLAY( window ),
899 (WXWindow)GDK_WINDOW_XWINDOW( window ), icons );
52d6235d 900 }
f618020a
MB
901}
902
7d9f12f3
VS
903// ----------------------------------------------------------------------------
904// frame state: maximized/iconized/normal
905// ----------------------------------------------------------------------------
906
907void wxTopLevelWindowGTK::Maximize(bool WXUNUSED(maximize))
908{
909 wxFAIL_MSG( _T("not implemented") );
910}
911
912bool wxTopLevelWindowGTK::IsMaximized() const
913{
914 // wxFAIL_MSG( _T("not implemented") );
915
916 // This is an approximation
917 return FALSE;
918}
919
920void wxTopLevelWindowGTK::Restore()
921{
922 wxFAIL_MSG( _T("not implemented") );
923}
924
925void wxTopLevelWindowGTK::Iconize( bool iconize )
926{
927 if (iconize)
928 {
929 GdkWindow *window = m_widget->window;
930
931 // you should do it later, for example from OnCreate() handler
932 wxCHECK_RET( window, _T("frame not created yet - can't iconize") );
933
934 XIconifyWindow( GDK_WINDOW_XDISPLAY( window ),
935 GDK_WINDOW_XWINDOW( window ),
936 DefaultScreen( GDK_DISPLAY() ) );
937 }
938}
939
940bool wxTopLevelWindowGTK::IsIconized() const
941{
942 return m_isIconized;
943}
944
945void wxTopLevelWindowGTK::SetIconizeState(bool iconize)
946{
947 if ( iconize != m_isIconized )
948 {
949 m_isIconized = iconize;
950 (void)SendIconizeEvent(iconize);
951 }
952}
953
5152b0e5
JS
954void wxTopLevelWindowGTK::AddGrab()
955{
956 if (!m_grabbed)
957 {
958 m_grabbed = TRUE;
959 gtk_grab_add( m_widget );
960 gtk_main();
961 gtk_grab_remove( m_widget );
962 }
963}
964
965void wxTopLevelWindowGTK::RemoveGrab()
966{
967 if (m_grabbed)
968 {
969 gtk_main_quit();
970 m_grabbed = FALSE;
971 }
972}
801225c1
RL
973
974// vi:sts=4:sw=4:et