Status bar positioned correctly, but no sign of the
[wxWidgets.git] / src / x11 / toplevel.cpp
1 ///////////////////////////////////////////////////////////////////////////////
2 // Name: x11/toplevel.cpp
3 // Purpose: implements wxTopLevelWindow for X11
4 // Author: Julian Smart
5 // Modified by:
6 // Created: 24.09.01
7 // RCS-ID: $Id$
8 // Copyright: (c) 2002 Julian Smart
9 // License: wxWindows licence
10 ///////////////////////////////////////////////////////////////////////////////
11
12 // ============================================================================
13 // declarations
14 // ============================================================================
15
16 // ----------------------------------------------------------------------------
17 // headers
18 // ----------------------------------------------------------------------------
19
20 #ifdef __GNUG__
21 #pragma implementation "toplevel.h"
22 #endif
23
24 // For compilers that support precompilation, includes "wx.h".
25 #include "wx/wxprec.h"
26
27 #ifdef __BORLANDC__
28 #pragma hdrstop
29 #endif
30
31 #ifndef WX_PRECOMP
32 #include "wx/app.h"
33 #include "wx/toplevel.h"
34 #include "wx/string.h"
35 #include "wx/log.h"
36 #include "wx/intl.h"
37 #include "wx/frame.h"
38 #include "wx/menu.h"
39 #include "wx/statusbr.h"
40 #endif //WX_PRECOMP
41
42 #include "wx/x11/private.h"
43
44 bool wxMWMIsRunning(Window w);
45
46 // ----------------------------------------------------------------------------
47 // wxTopLevelWindowX11 creation
48 // ----------------------------------------------------------------------------
49
50 void wxTopLevelWindowX11::Init()
51 {
52 m_iconized =
53 m_maximizeOnShow = FALSE;
54
55 // unlike (almost?) all other windows, frames are created hidden
56 m_isShown = FALSE;
57
58 // Data to save/restore when calling ShowFullScreen
59 m_fsStyle = 0;
60 m_fsIsMaximized = FALSE;
61 m_fsIsShowing = FALSE;
62 }
63
64 bool wxTopLevelWindowX11::Create(wxWindow *parent,
65 wxWindowID id,
66 const wxString& title,
67 const wxPoint& pos,
68 const wxSize& size,
69 long style,
70 const wxString& name)
71 {
72 // init our fields
73 Init();
74
75 m_windowStyle = style;
76 m_parent = parent;
77
78 SetName(name);
79
80 m_windowId = id == -1 ? NewControlId() : id;
81
82 if (parent)
83 parent->AddChild(this);
84
85 wxTopLevelWindows.Append(this);
86
87 Display *xdisplay = wxGlobalDisplay();
88 int xscreen = DefaultScreen( xdisplay );
89 Visual *xvisual = DefaultVisual( xdisplay, xscreen );
90 Window xparent = RootWindow( xdisplay, xscreen );
91
92 XSetWindowAttributes xattributes;
93 XSizeHints size_hints;
94 XWMHints wm_hints;
95
96 long xattributes_mask =
97 CWOverrideRedirect |
98 CWBorderPixel | CWBackPixel;
99 xattributes.background_pixel = BlackPixel( xdisplay, xscreen );
100 xattributes.border_pixel = BlackPixel( xdisplay, xscreen );
101 xattributes.override_redirect = False;
102
103 Window xwindow = XCreateWindow( xdisplay, xparent, pos.x, pos.y, size.x, size.y,
104 0, DefaultDepth(xdisplay,xscreen), InputOutput, xvisual, xattributes_mask, &xattributes );
105 m_mainWidget = (WXWindow) xwindow;
106
107 XSelectInput( xdisplay, xwindow,
108 ExposureMask | KeyPressMask | KeyReleaseMask | ButtonPressMask | ButtonReleaseMask |
109 ButtonMotionMask | EnterWindowMask | LeaveWindowMask | PointerMotionMask |
110 KeymapStateMask | FocusChangeMask | ColormapChangeMask | StructureNotifyMask |
111 PropertyChangeMask );
112
113 wxAddWindowToTable( xwindow, (wxWindow*) this );
114
115 XSetTransientForHint( xdisplay, xwindow, xparent );
116
117 size_hints.flags = PSize;
118 size_hints.width = size.x;
119 size_hints.height = size.y;
120 XSetWMNormalHints( xdisplay, xwindow, &size_hints);
121
122 wm_hints.flags = InputHint | StateHint /* | WindowGroupHint */;
123 wm_hints.input = True;
124 wm_hints.initial_state = NormalState;
125 XSetWMHints( xdisplay, xwindow, &wm_hints);
126
127 Atom wm_delete_window = XInternAtom( xdisplay, "WM_DELETE_WINDOW", False);
128 XSetWMProtocols( xdisplay, xwindow, &wm_delete_window, 1);
129
130 wxSetWMDecorations((Window) GetMainWindow(), style);
131
132 SetTitle(title);
133
134 return TRUE;
135 }
136
137 wxTopLevelWindowX11::~wxTopLevelWindowX11()
138 {
139 wxTopLevelWindows.DeleteObject(this);
140
141 // If this is the last top-level window, exit.
142 if ( wxTheApp && (wxTopLevelWindows.Number() == 0) )
143 {
144 wxTheApp->SetTopWindow(NULL);
145
146 if (wxTheApp->GetExitOnFrameDelete())
147 {
148 // Signal to the app that we're going to close
149 wxTheApp->ExitMainLoop();
150 }
151 }
152 }
153
154 // ----------------------------------------------------------------------------
155 // wxTopLevelWindowX11 showing
156 // ----------------------------------------------------------------------------
157
158 bool wxTopLevelWindowX11::Show(bool show)
159 {
160 return wxWindowX11::Show(show);
161 }
162
163 // ----------------------------------------------------------------------------
164 // wxTopLevelWindowX11 maximize/minimize
165 // ----------------------------------------------------------------------------
166
167 void wxTopLevelWindowX11::Maximize(bool maximize)
168 {
169 // TODO
170 }
171
172 bool wxTopLevelWindowX11::IsMaximized() const
173 {
174 // TODO
175 return TRUE;
176 }
177
178 void wxTopLevelWindowX11::Iconize(bool iconize)
179 {
180 if (!m_iconized && GetMainWindow())
181 {
182 if (XIconifyWindow(wxGlobalDisplay(),
183 (Window) GetMainWindow(), DefaultScreen(wxGlobalDisplay())) != 0)
184 m_iconized = TRUE;
185 }
186 }
187
188 bool wxTopLevelWindowX11::IsIconized() const
189 {
190 return m_iconized;
191 }
192
193 void wxTopLevelWindowX11::Restore()
194 {
195 // This is the way to deiconify the window, according to the X FAQ
196 if (m_iconized && GetMainWindow())
197 {
198 XMapWindow(wxGlobalDisplay(), (Window) GetMainWindow());
199 m_iconized = FALSE;
200 }
201 }
202
203 // ----------------------------------------------------------------------------
204 // wxTopLevelWindowX11 fullscreen
205 // ----------------------------------------------------------------------------
206
207 bool wxTopLevelWindowX11::ShowFullScreen(bool show, long style)
208 {
209 if (show)
210 {
211 if (IsFullScreen())
212 return FALSE;
213
214 m_fsIsShowing = TRUE;
215 m_fsStyle = style;
216
217 // TODO
218
219 return TRUE;
220 }
221 else
222 {
223 if (!IsFullScreen())
224 return FALSE;
225
226 m_fsIsShowing = FALSE;
227
228 // TODO
229 return TRUE;
230 }
231 }
232
233 // ----------------------------------------------------------------------------
234 // wxTopLevelWindowX11 misc
235 // ----------------------------------------------------------------------------
236
237 void wxTopLevelWindowX11::SetIcon(const wxIcon& icon)
238 {
239 // this sets m_icon
240 wxTopLevelWindowBase::SetIcon(icon);
241
242 if (icon.Ok() && GetMainWindow())
243 {
244 XWMHints *wmHints = XAllocWMHints();
245 wmHints->icon_pixmap = (Pixmap) icon.GetPixmap();
246
247 wmHints->flags = IconPixmapHint;
248
249 if (icon.GetMask())
250 {
251 wmHints->flags |= IconMaskHint;
252 wmHints->icon_mask = (Pixmap) icon.GetMask()->GetPixmap();
253 }
254
255 XSetWMHints(wxGlobalDisplay(), (Window) GetMainWindow(), wmHints);
256 XFree(wmHints);
257 }
258 }
259
260 void wxTopLevelWindowX11::SetTitle(const wxString& title)
261 {
262 m_title = title;
263 if (GetMainWindow())
264 {
265 XStoreName(wxGlobalDisplay(), (Window) GetMainWindow(),
266 (const char*) title);
267 XSetIconName(wxGlobalDisplay(), (Window) GetMainWindow(),
268 (const char*) title);
269
270 // Use this if the platform doesn't supply the above functions.
271 #if 0
272 XTextProperty textProperty;
273 textProperty.value = (unsigned char*) title;
274 textProperty.encoding = XA_STRING;
275 textProperty.format = 8;
276 textProperty.nitems = 1;
277
278 XSetTextProperty(wxGlobalDisplay(), (Window) GetMainWindow(),
279 & textProperty, WM_NAME);
280 #endif
281 }
282 }
283
284 wxString wxTopLevelWindowX11::GetTitle() const
285 {
286 return m_title;
287 }
288
289 #ifndef MWM_DECOR_BORDER
290 /* bit definitions for MwmHints.flags */
291 #define MWM_HINTS_FUNCTIONS (1L << 0)
292 #define MWM_HINTS_DECORATIONS (1L << 1)
293 #define MWM_HINTS_INPUT_MODE (1L << 2)
294 #define MWM_HINTS_STATUS (1L << 3)
295
296 #define MWM_DECOR_ALL (1L << 0)
297 #define MWM_DECOR_BORDER (1L << 1)
298 #define MWM_DECOR_RESIZEH (1L << 2)
299 #define MWM_DECOR_TITLE (1L << 3)
300 #define MWM_DECOR_MENU (1L << 4)
301 #define MWM_DECOR_MINIMIZE (1L << 5)
302 #define MWM_DECOR_MAXIMIZE (1L << 6)
303 #endif
304
305 struct MwmHints {
306 long flags;
307 long functions;
308 long decorations;
309 long input_mode;
310 };
311
312 #define PROP_MOTIF_WM_HINTS_ELEMENTS 5
313
314 // Set the window manager decorations according to the
315 // given wxWindows style
316 bool wxSetWMDecorations(Window w, long style)
317 {
318 if (!wxMWMIsRunning(w))
319 return FALSE;
320
321 Atom mwm_wm_hints = XInternAtom(wxGlobalDisplay(),"_MOTIF_WM_HINTS", False);
322 MwmHints hints;
323 hints.flags = 0;
324 hints.decorations = 0;
325
326 if (style & wxRESIZE_BORDER)
327 {
328 hints.flags |= MWM_HINTS_DECORATIONS;
329 hints.decorations |= MWM_DECOR_RESIZEH;
330 }
331
332 if (style & wxSYSTEM_MENU)
333 {
334 hints.flags |= MWM_HINTS_DECORATIONS;
335 hints.decorations |= MWM_DECOR_MENU;
336 }
337
338 if ((style & wxCAPTION) ||
339 (style & wxTINY_CAPTION_HORIZ) ||
340 (style & wxTINY_CAPTION_VERT))
341 {
342 hints.flags |= MWM_HINTS_DECORATIONS;
343 hints.decorations |= MWM_DECOR_TITLE;
344 }
345
346 if (style & wxTHICK_FRAME)
347 {
348 hints.flags |= MWM_HINTS_DECORATIONS;
349 hints.decorations |= MWM_DECOR_BORDER;
350 }
351
352 if (style & wxTHICK_FRAME)
353 {
354 hints.flags |= MWM_HINTS_DECORATIONS;
355 hints.decorations |= MWM_DECOR_BORDER;
356 }
357
358 if (style & wxMINIMIZE_BOX)
359 {
360 hints.flags |= MWM_HINTS_DECORATIONS;
361 hints.decorations |= MWM_DECOR_MINIMIZE;
362 }
363
364 if (style & wxMAXIMIZE_BOX)
365 {
366 hints.flags |= MWM_HINTS_DECORATIONS;
367 hints.decorations |= MWM_DECOR_MAXIMIZE;
368 }
369
370 XChangeProperty(wxGlobalDisplay(),
371 w,
372 mwm_wm_hints, mwm_wm_hints,
373 32, PropModeReplace,
374 (unsigned char *) &hints, PROP_MOTIF_WM_HINTS_ELEMENTS);
375
376 return TRUE;
377 }
378
379 bool wxMWMIsRunning(Window w)
380 {
381 Display *dpy = (Display*)wxGetDisplay();
382 Atom motifWmInfo = XInternAtom(dpy, "_MOTIF_WM_INFO", False);
383
384 unsigned long length, bytesafter;
385 unsigned char value[20];
386 unsigned char *ptr = &value[0];
387 int ret, format;
388 Atom type;
389
390 type = format = length = 0;
391 value[0] = 0;
392
393 ret = XGetWindowProperty(wxGlobalDisplay(), w, motifWmInfo,
394 0L, 2, False, motifWmInfo,
395 &type, &format, &length, &bytesafter, &ptr);
396
397 return (ret == Success);
398 }
399
400 // For implementation purposes - sometimes decorations make the client area
401 // smaller
402 wxPoint wxTopLevelWindowX11::GetClientAreaOrigin() const
403 {
404 // In fact wxFrame::GetClientAreaOrigin
405 // does the required calculation already.
406 #if 0
407 if (this->IsKindOf(CLASSINFO(wxFrame)))
408 {
409 wxFrame* frame = (wxFrame*) this;
410 if (frame->GetMenuBar())
411 return wxPoint(0, frame->GetMenuBar()->GetSize().y);
412 }
413 #endif
414 return wxPoint(0, 0);
415 }
416
417 void wxTopLevelWindowX11::DoGetClientSize( int *width, int *height ) const
418 {
419 wxWindowX11::DoGetClientSize(width, height);
420 // Done by wxTopLevelWindow
421 #if 0
422 if (this->IsKindOf(CLASSINFO(wxFrame)))
423 {
424 wxFrame* frame = (wxFrame*) this;
425 if (frame->GetMenuBar())
426 (*height) -= frame->GetMenuBar()->GetSize().y;
427 if (frame->GetStatusBar())
428 (*height) -= frame->GetStatusBar()->GetSize().y;
429 }
430 #endif
431 }
432
433 void wxTopLevelWindowX11::DoSetClientSize(int width, int height)
434 {
435 wxWindowX11::DoSetClientSize(width, height);
436 #if 0
437 if (!GetMainWindow())
438 return;
439
440 XWindowChanges windowChanges;
441 int valueMask = 0;
442
443 if (width != -1)
444 {
445 windowChanges.width = width ;
446 valueMask |= CWWidth;
447 }
448 if (height != -1)
449 {
450 windowChanges.height = height ;
451 valueMask |= CWHeight;
452 }
453 XConfigureWindow(wxGlobalDisplay(), (Window) GetMainWindow(),
454 valueMask, & windowChanges);
455 #endif
456 }