1 ///////////////////////////////////////////////////////////////////////////////
2 // Name:        src/os2/toplevel.cpp
3 // Purpose:     implements wxTopLevelWindow for OS/2
4 // Author:      Vadim Zeitlin
5 // Modified by:
6 // Created:     30.12.01
7 // Copyright:   (c) 2001 SciTech Software, Inc. (www.scitechsoft.com)
8 // Licence:     wxWindows licence
9 ///////////////////////////////////////////////////////////////////////////////
10 
11 // ============================================================================
12 // declarations
13 // ============================================================================
14 
15 // ----------------------------------------------------------------------------
16 // headers
17 // ----------------------------------------------------------------------------
18 
19 // For compilers that support precompilation, includes "wx.h".
20 #include "wx/wxprec.h"
21 
22 #ifdef __BORLANDC__
23     #pragma hdrstop
24 #endif
25 
26 #include "wx/toplevel.h"
27 
28 #ifndef WX_PRECOMP
29     #include "wx/app.h"
30     #include "wx/dialog.h"
31     #include "wx/string.h"
32     #include "wx/log.h"
33     #include "wx/intl.h"
34     #include "wx/frame.h"
35     #include "wx/control.h"
36     #include "wx/containr.h"        // wxSetFocusToChild()
37     #include "wx/settings.h"
38     #include "wx/module.h"        // wxSetFocusToChild()
39 #endif //WX_PRECOMP
40 
41 #include "wx/os2/private.h"
42 
43 // ----------------------------------------------------------------------------
44 // stubs for missing functions under MicroWindows
45 // ----------------------------------------------------------------------------
46 
47 
48 // ----------------------------------------------------------------------------
49 // globals
50 // ----------------------------------------------------------------------------
51 
52 // the name of the default wxWidgets class
53 extern void wxAssociateWinWithHandle( HWND hWnd, wxWindowOS2* pWin );
54 
55 bool wxTopLevelWindowOS2::m_sbInitialized = false;
56 wxWindow* wxTopLevelWindowOS2::m_spHiddenParent = NULL;
57 
58 // ============================================================================
59 // wxTopLevelWindowOS2 implementation
60 // ============================================================================
61 
BEGIN_EVENT_TABLE(wxTopLevelWindowOS2,wxTopLevelWindowBase)62 BEGIN_EVENT_TABLE(wxTopLevelWindowOS2, wxTopLevelWindowBase)
63     EVT_ACTIVATE(wxTopLevelWindowOS2::OnActivate)
64 END_EVENT_TABLE()
65 
66 // ============================================================================
67 // wxTopLevelWindowMSW implementation
68 // ============================================================================
69 
70 // Dialog window proc
71 MRESULT EXPENTRY wxDlgProc( HWND WXUNUSED(hWnd)
72                            ,UINT uMessage
73                            ,void * WXUNUSED(wParam)
74                            ,void * WXUNUSED(lParam)
75                           )
76 {
77     switch(uMessage)
78     {
79         case WM_INITDLG:
80             //
81             // For this message, returning TRUE tells system to set focus to
82             // the first control in the dialog box, but we set the focus
83             // ourselves, however in OS/2 we must return true to enable the dialog
84             //
85             return (MRESULT)TRUE;
86         default:
87             //
88             // For all the other ones, FALSE means that we didn't process the
89             // message
90             //
91             return (MRESULT)FALSE;
92     }
93 } // end of wxDlgProc
94 
95 // ----------------------------------------------------------------------------
96 // wxTLWHiddenParentModule: used to manage the hidden parent window (we need a
97 // module to ensure that the window is always deleted)
98 // ----------------------------------------------------------------------------
99 
100 class wxTLWHiddenParentModule : public wxModule
101 {
102 public:
103     //
104     // Module init/finalize
105     //
106     virtual bool OnInit(void);
107     virtual void OnExit(void);
108 
109     //
110     // Get the hidden window (creates on demand)
111     //
112     static HWND GetHWND(void);
113 
114 private:
115     //
116     // The HWND of the hidden parent
117     //
118     static HWND m_shWnd;
119 
120     //
121     // The class used to create it
122     //
123     static const wxChar* m_szClassName;
124     DECLARE_DYNAMIC_CLASS(wxTLWHiddenParentModule)
125 }; // end of CLASS wxTLWHiddenParentModule
126 
IMPLEMENT_DYNAMIC_CLASS(wxTLWHiddenParentModule,wxModule)127 IMPLEMENT_DYNAMIC_CLASS(wxTLWHiddenParentModule, wxModule)
128 
129 // ----------------------------------------------------------------------------
130 // wxTopLevelWindowOS2 creation
131 // ----------------------------------------------------------------------------
132 
133 void wxTopLevelWindowOS2::Init()
134 {
135     m_bIconized = m_bMaximizeOnShow = false;
136 
137     //
138     // Unlike (almost?) all other windows, frames are created hidden
139     //
140     m_isShown = false;
141 
142     //
143     // Data to save/restore when calling ShowFullScreen
144     m_lFsStyle          = 0;
145     m_lFsOldWindowStyle = 0;
146     m_bFsIsMaximized    = false;
147     m_bFsIsShowing      = false;
148 
149     m_hFrame    = NULLHANDLE;
150     memset(&m_vSwp, 0, sizeof(SWP));
151     memset(&m_vSwpClient, 0, sizeof(SWP));
152     m_pWinLastFocused = NULL;
153 } // end of wxTopLevelWindowIOS2::Init
154 
OnActivate(wxActivateEvent & rEvent)155 void wxTopLevelWindowOS2::OnActivate(
156   wxActivateEvent&                  rEvent
157 )
158 {
159     if (rEvent.GetActive())
160     {
161         //
162         // Restore focus to the child which was last focused
163         //
164         wxLogTrace(wxT("focus"), wxT("wxTLW %08lx activated."), m_hWnd);
165 
166         wxWindow*                   pParent = m_pWinLastFocused ? m_pWinLastFocused->GetParent()
167                                                                 : NULL;
168         if (!pParent)
169         {
170             pParent = this;
171         }
172 
173         wxSetFocusToChild( pParent
174                           ,&m_pWinLastFocused
175                          );
176     }
177     else // deactivating
178     {
179         //
180         // Remember the last focused child if it is our child
181         //
182         m_pWinLastFocused = FindFocus();
183 
184         //
185         // So we NULL it out if it's a child from some other frame
186         //
187         wxWindow*                   pWin = m_pWinLastFocused;
188 
189         while (pWin)
190         {
191             if (pWin->IsTopLevel())
192             {
193                 if (pWin != this)
194                 {
195                     m_pWinLastFocused = NULL;
196                 }
197                 break;
198             }
199             pWin = pWin->GetParent();
200         }
201 
202         wxLogTrace(wxT("focus"),
203                    wxT("wxTLW %08lx deactivated, last focused: %08lx."),
204                    m_hWnd,
205                    m_pWinLastFocused ? GetHwndOf(m_pWinLastFocused)
206                                      : NULL);
207         rEvent.Skip();
208     }
209 } // end of wxTopLevelWindowOS2::OnActivate
210 
OS2GetStyle(long lStyle,WXDWORD * pdwExflags) const211 WXDWORD wxTopLevelWindowOS2::OS2GetStyle(
212   long                              lStyle
213 , WXDWORD*                          pdwExflags
214 ) const
215 {
216     long                            lMsflags = wxWindow::OS2GetStyle( (lStyle & ~wxBORDER_MASK) | wxBORDER_NONE
217                                                                      ,pdwExflags
218                                                                     );
219 
220     if ((lStyle & wxDEFAULT_FRAME_STYLE) == wxDEFAULT_FRAME_STYLE)
221         lMsflags |= FCF_SIZEBORDER | FCF_TITLEBAR | FCF_SYSMENU |
222                     FCF_MINMAX | FCF_TASKLIST;
223 
224     if ((lStyle & wxCAPTION) == wxCAPTION)
225         lMsflags |= FCF_TASKLIST;
226     else
227         lMsflags |= FCF_NOMOVEWITHOWNER;
228 
229     if ((lStyle & wxVSCROLL) == wxVSCROLL)
230         lMsflags |= FCF_VERTSCROLL;
231     if ((lStyle & wxHSCROLL) == wxHSCROLL)
232         lMsflags |= FCF_HORZSCROLL;
233     if (lStyle & wxMINIMIZE_BOX)
234         lMsflags |= FCF_MINBUTTON;
235     if (lStyle & wxMAXIMIZE_BOX)
236         lMsflags |= FCF_MAXBUTTON;
237     if (lStyle & wxRESIZE_BORDER)
238         lMsflags |= FCF_DLGBORDER;
239     if (lStyle & wxSYSTEM_MENU)
240         lMsflags |= FCF_SYSMENU;
241     if (lStyle & wxCAPTION)
242         lMsflags |= FCF_TASKLIST;
243     if (lStyle & wxCLIP_CHILDREN)
244     {
245         // Invalid for frame windows under PM
246     }
247 
248     if (lStyle & wxTINY_CAPTION)
249         lMsflags |= FCF_TASKLIST;
250 
251     if ((lStyle & wxRESIZE_BORDER) == 0)
252         lMsflags |= FCF_BORDER;
253     if (lStyle & wxFRAME_TOOL_WINDOW)
254         *pdwExflags = kFrameToolWindow;
255 
256     if (lStyle & wxSTAY_ON_TOP)
257         lMsflags |= FCF_SYSMODAL;
258 
259     return lMsflags;
260 } // end of wxTopLevelWindowOS2::OS2GetCreateWindowFlags
261 
OS2GetParent() const262 WXHWND wxTopLevelWindowOS2::OS2GetParent() const
263 {
264     HWND                            hWndParent = NULL;
265 
266     //
267     // For the frames without wxFRAME_FLOAT_ON_PARENT style we should use NULL
268     // parent HWND or it would be always on top of its parent which is not what
269     // we usually want (in fact, we only want it for frames with the
270     // wxFRAME_FLOAT_ON_PARENT flag)
271     //
272     if (HasFlag(wxFRAME_FLOAT_ON_PARENT) )
273     {
274         const wxWindow*             pParent = GetParent();
275 
276         if (!pParent)
277         {
278             //
279             // This flag doesn't make sense then and will be ignored
280             //
281             wxFAIL_MSG( wxT("wxFRAME_FLOAT_ON_PARENT but no parent?") );
282         }
283         else
284         {
285             hWndParent = GetHwndOf(pParent);
286         }
287     }
288     //else: don't float on parent, must not be owned
289 
290     //
291     // Now deal with the 2nd taskbar-related problem (see comments above in
292     // OS2GetStyle())
293     //
294     if (HasFlag(wxFRAME_NO_TASKBAR) && !hWndParent)
295     {
296         //
297         // Use hidden parent
298         //
299         hWndParent = wxTLWHiddenParentModule::GetHWND();
300     }
301     return (WXHWND)hWndParent;
302 } // end of wxTopLevelWindowOS2::OS2GetParent
303 
304 
CreateDialog(ULONG ulDlgTemplate,const wxString & WXUNUSED (rsTitle),const wxPoint & rPos,const wxSize & rSize)305 bool wxTopLevelWindowOS2::CreateDialog( ULONG           ulDlgTemplate,
306                                         const wxString& WXUNUSED(rsTitle),
307                                         const wxPoint&  rPos,
308                                         const wxSize&   rSize )
309 {
310     wxWindow*                       pParent = GetParent();
311 
312     //
313     // For the dialogs without wxDIALOG_NO_PARENT style, use the top level
314     // app window as parent - this avoids creating modal dialogs without
315     // parent
316     //
317     if (!pParent && !(GetWindowStyleFlag() & wxDIALOG_NO_PARENT))
318     {
319         pParent = wxTheApp->GetTopWindow();
320 
321         if (pParent)
322         {
323             //
324             // Don't use transient windows as parents, this is dangerous as it
325             // can lead to a crash if the parent is destroyed before the child
326             //
327             // also don't use the window which is currently hidden as then the
328             // dialog would be hidden as well
329             if ((pParent->GetExtraStyle() & wxWS_EX_TRANSIENT) ||
330                  !pParent->IsShown())
331             {
332                 pParent = NULL;
333             }
334         }
335     }
336 
337     HWND                            hWndDlg;
338     HWND                            hWndOwner;
339 
340     if (pParent)
341         hWndOwner = GetHwndOf(pParent);
342     else
343         hWndOwner = HWND_DESKTOP;
344 
345     hWndDlg = ::WinLoadDlg( HWND_DESKTOP
346                            ,hWndOwner
347                            ,(PFNWP)wxDlgProc
348                            ,NULL
349                            ,(ULONG)ulDlgTemplate
350                            ,(PVOID)this
351                           );
352 
353     m_hWnd = (WXHWND) hWndDlg;
354 
355     if ( !m_hWnd )
356     {
357         wxFAIL_MSG(wxT("Did you forget to include wx/os2/wx.rc in your resources?"));
358 
359         wxLogSysError(wxT("Can't create dialog using template '%ld'"), ulDlgTemplate);
360 
361         return false;
362     }
363 
364     //
365     // Move the dialog to its initial position without forcing repainting
366     //
367     int                             nX;
368     int                             nY;
369     int                             nWidth;
370     int                             nHeight;
371 
372     if (!OS2GetCreateWindowCoords( rPos
373                                   ,rSize
374                                   ,nX
375                                   ,nY
376                                   ,nWidth
377                                   ,nHeight
378                                  ))
379     {
380         nX = nWidth = (int)CW_USEDEFAULT;
381     }
382 
383     //
384     // We can't use CW_USEDEFAULT here as we're not calling CreateWindow()
385     // and passing CW_USEDEFAULT to MoveWindow() results in resizing the
386     // window to (0, 0) size which breaks quite a lot of things, e.g. the
387     // sizer calculation in wxSizer::Fit()
388     //
389     if (nWidth == (int)CW_USEDEFAULT)
390     {
391         //
392         // The exact number doesn't matter, the dialog will be resized
393         // again soon anyhow but it should be big enough to allow
394         // calculation relying on "totalSize - clientSize > 0" work, i.e.
395         // at least greater than the title bar height
396         //
397         nWidth = nHeight = 100;
398     }
399     if (nX == (int)CW_USEDEFAULT)
400     {
401         //
402         // Centre it on the screen - what else can we do?
403         //
404         wxSize                      vSizeDpy = wxGetDisplaySize();
405 
406         nX = (vSizeDpy.x - nWidth) / 2;
407         nY = (vSizeDpy.y - nHeight) / 2;
408     }
409     SetBackgroundColour(wxSystemSettings::GetColour(wxSYS_COLOUR_APPWORKSPACE));
410 
411     LONG                            lColor = (LONG)m_backgroundColour.GetPixel();
412 
413     if (!::WinSetPresParam( m_hWnd
414                            ,PP_BACKGROUNDCOLOR
415                            ,sizeof(LONG)
416                            ,(PVOID)&lColor
417                           ))
418     {
419         return false;
420     }
421 
422     // Convert to OS/2 coordinates
423     nY = GetOS2ParentHeight(pParent) - nY - nHeight;
424 
425     ::WinSetWindowPos( GetHwnd()
426                       ,HWND_TOP
427                       ,nX
428                       ,nY
429                       ,nWidth
430                       ,nHeight
431                       ,SWP_MOVE | SWP_SIZE | SWP_ZORDER | SWP_SHOW | SWP_ACTIVATE
432                      );
433     ::WinQueryWindowPos(GetHwnd(), GetSwp());
434     m_hFrame = m_hWnd;
435     SubclassWin(m_hWnd);
436     return true;
437 } // end of wxTopLevelWindowOS2::CreateDialog
438 
CreateFrame(const wxString & rsTitle,const wxPoint & rPos,const wxSize & rSize)439 bool wxTopLevelWindowOS2::CreateFrame( const wxString& rsTitle,
440                                        const wxPoint& rPos,
441                                        const wxSize& rSize )
442 {
443     WXDWORD    lExflags;
444     WXDWORD    lFlags = OS2GetCreateWindowFlags(&lExflags);
445     long       lStyle = GetWindowStyleFlag();
446     int        nX = rPos.x;
447     int        nY = rPos.y;
448     int        nWidth = rSize.x;
449     int        nHeight = rSize.y;
450     ULONG      ulStyleFlags = 0L;
451     ERRORID    vError;
452     wxString   sError;
453     wxWindow*  pParent = GetParent();
454     HWND       hParent;
455     HWND       hFrame;
456     HWND       hClient;
457 
458     if (pParent)
459         hParent = GetHwndOf(pParent);
460     else
461         hParent = HWND_DESKTOP;
462 
463     if ((lStyle & wxMINIMIZE) || (lStyle & wxICONIZE))
464         ulStyleFlags |= WS_MINIMIZED;
465     if (lStyle & wxMAXIMIZE)
466         ulStyleFlags |= WS_MAXIMIZED;
467 
468     //
469     // Clear the visible flag, we always call show
470     //
471     ulStyleFlags &= (unsigned long)~WS_VISIBLE;
472     m_bIconized = false;
473 
474     //
475     // Create the frame window:  We break ranks with other ports now
476     // and instead of calling down into the base wxWindow class' OS2Create
477     // we do all our own stuff here.  We will set the needed pieces
478     // of wxWindow manually, here.
479     //
480 
481      hFrame = ::WinCreateStdWindow( hParent
482                                    ,ulStyleFlags          // frame-window style
483                                    ,(PULONG)&lFlags       // window style
484                                    ,wxString(wxFrameClassName).c_str() // class name
485                                    ,rsTitle.c_str()       // window title
486                                    ,0L                    // default client style
487                                    ,NULLHANDLE            // resource in executable file
488                                    ,0                     // resource id
489                                    ,&hClient              // receives client window handle
490                                   );
491     if (!hFrame)
492     {
493         vError = ::WinGetLastError(vHabmain);
494         sError = wxPMErrorToStr(vError);
495         wxLogError(wxT("Error creating frame. Error: %s\n"), sError.c_str());
496         return false;
497     }
498 
499     //
500     // wxWindow class' m_hWnd set here and needed associations
501     //
502     m_hFrame = hFrame;
503     m_hWnd   = hClient;
504     wxAssociateWinWithHandle(m_hWnd, this);
505     wxAssociateWinWithHandle(m_hFrame, this);
506 
507     SetBackgroundColour(wxSystemSettings::GetColour(wxSYS_COLOUR_APPWORKSPACE));
508 
509     LONG                            lColor = (LONG)m_backgroundColour.GetPixel();
510 
511     if (!::WinSetPresParam( m_hWnd
512                            ,PP_BACKGROUNDCOLOR
513                            ,sizeof(LONG)
514                            ,(PVOID)&lColor
515                           ))
516     {
517         vError = ::WinGetLastError(vHabmain);
518         sError = wxPMErrorToStr(vError);
519         wxLogError(wxT("Error creating frame. Error: %s\n"), sError.c_str());
520         return false;
521     }
522 
523     //
524     // Now need to subclass window.  Instead of calling the SubClassWin in wxWindow
525     // we manually subclass here because we don't want to use the main wxWndProc
526     // by default
527     //
528     m_fnOldWndProc = (WXFARPROC) ::WinSubclassWindow(m_hFrame, (PFNWP)wxFrameMainWndProc);
529 
530     //
531     // Now size everything.  If adding a menu the client will need to be resized.
532     //
533 
534     if (!OS2GetCreateWindowCoords( rPos
535                                   ,rSize
536                                   ,nX
537                                   ,nY
538                                   ,nWidth
539                                   ,nHeight
540                                  ))
541     {
542         nX = nWidth = (int)CW_USEDEFAULT;
543     }
544 
545     //
546     // We can't use CW_USEDEFAULT here as we're not calling CreateWindow()
547     // and passing CW_USEDEFAULT to MoveWindow() results in resizing the
548     // window to (0, 0) size which breaks quite a lot of things, e.g. the
549     // sizer calculation in wxSizer::Fit()
550     //
551     if (nWidth == (int)CW_USEDEFAULT)
552     {
553         //
554         // The exact number doesn't matter, the dialog will be resized
555         // again soon anyhow but it should be big enough to allow
556         // calculation relying on "totalSize - clientSize > 0" work, i.e.
557         // at least greater than the title bar height
558         //
559         nWidth = nHeight = 100;
560     }
561     if (nX == (int)CW_USEDEFAULT)
562     {
563         //
564         // Centre it on the screen for now - what else can we do?
565         // TODO: We could try FCF_SHELLPOSITION but it will require moving
566         //       things around a bit.
567         //
568         wxSize                      vSizeDpy = wxGetDisplaySize();
569 
570         nX = (vSizeDpy.x - nWidth) / 2;
571         nY = (vSizeDpy.y - nHeight) / 2;
572     }
573 
574     // Convert to OS/2 coordinates
575     nY = GetOS2ParentHeight(pParent) - nY - nHeight;
576 
577     if (!::WinSetWindowPos( m_hFrame
578                            ,HWND_TOP
579                            ,nX
580                            ,nY
581                            ,nWidth
582                            ,nHeight
583                            ,SWP_SIZE | SWP_MOVE | SWP_ACTIVATE | SWP_ZORDER
584                           ))
585     {
586         vError = ::WinGetLastError(vHabmain);
587         sError = wxPMErrorToStr(vError);
588         wxLogError(wxT("Error sizing frame. Error: %s\n"), sError.c_str());
589         return false;
590     }
591     lStyle =  ::WinQueryWindowULong( m_hWnd
592                                     ,QWL_STYLE
593                                    );
594     lStyle |= WS_CLIPCHILDREN;
595     ::WinSetWindowULong( m_hWnd
596                         ,QWL_STYLE
597                         ,lStyle
598                        );
599     return true;
600 } // end of wxTopLevelWindowOS2::CreateFrame
601 
Create(wxWindow * pParent,wxWindowID vId,const wxString & rsTitle,const wxPoint & rPos,const wxSize & rSizeOrig,long lStyle,const wxString & rsName)602 bool wxTopLevelWindowOS2::Create(
603   wxWindow*                         pParent
604 , wxWindowID                        vId
605 , const wxString&                   rsTitle
606 , const wxPoint&                    rPos
607 , const wxSize&                     rSizeOrig
608 , long                              lStyle
609 , const wxString&                   rsName
610 )
611 {
612     //
613     // Init our fields
614     //
615     Init();
616     m_windowStyle = lStyle;
617     SetName(rsName);
618     m_windowId = vId == -1 ? NewControlId() : vId;
619 
620     // always create a frame of some reasonable, even if arbitrary, size (at
621     // least for MSW compatibility)
622     wxSize rSize = rSizeOrig;
623     if ( rSize.x == -1 || rSize.y == -1 )
624     {
625         wxSize sizeDpy = wxGetDisplaySize();
626         if ( rSize.x == -1 )
627             rSize.x = sizeDpy.x / 3;
628         if ( rSize.y == -1 )
629             rSize.y = sizeDpy.y / 5;
630     }
631 
632     wxTopLevelWindows.Append(this);
633     if (pParent)
634         pParent->AddChild(this);
635 
636     if (GetExtraStyle() & wxTOPLEVEL_EX_DIALOG)
637     {
638         //
639         // We have different dialog templates to allow creation of dialogs
640         // with & without captions under OS2indows, resizable or not (but a
641         // resizable dialog always has caption - otherwise it would look too
642         // strange)
643         //
644         ULONG                       ulDlgTemplate;
645 
646         if (lStyle & wxRESIZE_BORDER)
647             ulDlgTemplate = (ULONG)kResizeableDialog;
648         else if (lStyle & wxCAPTION)
649             ulDlgTemplate = (ULONG)kCaptionDialog;
650         else
651             ulDlgTemplate = (ULONG)kNoCaptionDialog;
652         return CreateDialog( ulDlgTemplate
653                             ,rsTitle
654                             ,rPos
655                             ,rSize
656                            );
657     }
658     else // !dialog
659     {
660         return CreateFrame( rsTitle
661                            ,rPos
662                            ,rSize
663                           );
664     }
665 } // end of wxTopLevelWindowOS2::Create
666 
~wxTopLevelWindowOS2()667 wxTopLevelWindowOS2::~wxTopLevelWindowOS2()
668 {
669     //
670     // After destroying an owned window, Windows activates the next top level
671     // window in Z order but it may be different from our owner (to reproduce
672     // this simply Alt-TAB to another application and back before closing the
673     // owned frame) whereas we always want to yield activation to our parent
674     //
675     if (HasFlag(wxFRAME_FLOAT_ON_PARENT))
676     {
677         wxWindow*                   pParent = GetParent();
678 
679         if (pParent)
680         {
681             ::WinSetWindowPos( GetHwndOf(pParent)
682                               ,HWND_TOP
683                               ,0, 0, 0, 0
684                               ,SWP_ZORDER
685                              );
686         }
687     }
688 } // end of wxTopLevelWindowOS2::~wxTopLevelWindowOS2
689 
690 // ----------------------------------------------------------------------------
691 // wxTopLevelWindowOS2 client size
692 // ----------------------------------------------------------------------------
693 
DoSetClientSize(int nWidth,int nHeight)694 void wxTopLevelWindowOS2::DoSetClientSize(
695   int                               nWidth
696 , int                               nHeight
697 )
698 {
699     //
700     // Call GetClientAreaOrigin() to take the toolbar into account
701     //
702     wxPoint                         vPt = GetClientAreaOrigin();
703 
704     nWidth  += vPt.x;
705     nHeight += vPt.y;
706 
707     wxWindow::DoSetClientSize( nWidth
708                               ,nHeight
709                              );
710 } // end of wxTopLevelWindowOS2::DoSetClientSize
711 
DoGetClientSize(int * pnX,int * pnY) const712 void wxTopLevelWindowOS2::DoGetClientSize(
713   int*                              pnX
714 , int*                              pnY
715 ) const
716 {
717     wxWindow::DoGetClientSize( pnX
718                               ,pnY
719                              );
720 
721     wxPoint                         vPt = GetClientAreaOrigin();
722 
723     if (pnX)
724         *pnX -= vPt.x;
725 
726     if (pnY)
727         *pnY += vPt.y;
728 } // end of wxTopLevelWindowOS2::DoGetClientSize
729 
730 // ----------------------------------------------------------------------------
731 // wxTopLevelWindowOS2 showing
732 // ----------------------------------------------------------------------------
733 
DoShowWindow(int nShowCmd)734 void wxTopLevelWindowOS2::DoShowWindow(
735   int                               nShowCmd
736 )
737 {
738     ::WinShowWindow(m_hFrame, (BOOL)(nShowCmd & SWP_SHOW));
739 
740     //
741     // Need to artificially send a size event as wxApps often expect to do some
742     // final child control sizing
743     SendSizeEvent();
744     m_bIconized = nShowCmd == SWP_MINIMIZE;
745 } // end of wxTopLevelWindowOS2::DoShowWindow
746 
Show(bool bShow)747 bool wxTopLevelWindowOS2::Show( bool bShow )
748 {
749     int nShowCmd;
750     SWP vSwp;
751 
752     if (bShow != IsShown() )
753     {
754         m_isShown = bShow;
755     }
756     else
757     {
758         return false;
759     }
760     if (bShow)
761     {
762         if (m_bMaximizeOnShow)
763         {
764             nShowCmd = SWP_MAXIMIZE;
765             m_bMaximizeOnShow = false;
766         }
767         else
768         {
769             nShowCmd = SWP_SHOW;
770         }
771     }
772     else // hide
773     {
774         nShowCmd = SWP_HIDE;
775     }
776     DoShowWindow(nShowCmd);
777 
778     if (bShow)
779     {
780         wxActivateEvent vEvent(wxEVT_ACTIVATE, true, m_windowId);
781 
782         ::WinQueryWindowPos(m_hFrame, &vSwp);
783         m_bIconized = ( vSwp.fl & SWP_MINIMIZE ) == SWP_MINIMIZE ;
784         ::WinQueryWindowPos(m_hWnd, &m_vSwpClient);
785         ::WinSendMsg(m_hFrame, WM_UPDATEFRAME, (MPARAM)~0, 0);
786         ::WinQueryWindowPos(m_hWnd, &vSwp);
787         ::WinEnableWindow(m_hFrame, TRUE);
788 
789         vEvent.SetEventObject(this);
790         HandleWindowEvent(vEvent);
791     }
792     else
793     {
794         //
795         // Try to highlight the correct window (the parent)
796         //
797         if (GetParent())
798         {
799             HWND hWndParent = GetHwndOf(GetParent());
800 
801             ::WinQueryWindowPos(hWndParent, &vSwp);
802             m_bIconized = (vSwp.fl & SWP_MINIMIZE)==SWP_MINIMIZE;
803             ::WinEnableWindow(hWndParent, TRUE);
804         }
805     }
806     return true;
807 } // end of wxTopLevelWindowOS2::Show
808 
809 // ----------------------------------------------------------------------------
810 // wxTopLevelWindowOS2 maximize/minimize
811 // ----------------------------------------------------------------------------
812 
Maximize(bool bMaximize)813 void wxTopLevelWindowOS2::Maximize(
814   bool                              bMaximize
815 )
816 {
817     if (IsShown())
818     {
819         //
820         // Just maximize it directly
821         //
822         DoShowWindow(bMaximize ? SWP_MAXIMIZE : SWP_RESTORE);
823     }
824     else // hidden
825     {
826         //
827         // We can't maximize the hidden frame because it shows it as well, so
828         // just remember that we should do it later in this case
829         //
830         m_bMaximizeOnShow = bMaximize;
831     }
832 } // end of wxTopLevelWindowOS2::Maximize
833 
IsMaximized() const834 bool wxTopLevelWindowOS2::IsMaximized() const
835 {
836     ::WinQueryWindowPos(m_hFrame, (PSWP)&m_vSwp);
837     return (m_vSwp.fl & SWP_MAXIMIZE) == SWP_MAXIMIZE;
838 } // end of wxTopLevelWindowOS2::IsMaximized
839 
SetTitle(const wxString & title)840 void wxTopLevelWindowOS2::SetTitle( const wxString& title)
841 {
842     SetLabel(title);
843 }
844 
GetTitle() const845 wxString wxTopLevelWindowOS2::GetTitle() const
846 {
847     return GetLabel();
848 }
849 
Iconize(bool bIconize)850 void wxTopLevelWindowOS2::Iconize( bool bIconize )
851 {
852     DoShowWindow(bIconize ? SWP_MINIMIZE : SWP_RESTORE);
853 } // end of wxTopLevelWindowOS2::Iconize
854 
IsIconized() const855 bool wxTopLevelWindowOS2::IsIconized() const
856 {
857     // also update the current state
858     ::WinQueryWindowPos(m_hFrame, (PSWP)&m_vSwp);
859     if (m_vSwp.fl & SWP_MINIMIZE)
860         ((wxTopLevelWindow*)this)->m_bIconized = true;
861     else
862         ((wxTopLevelWindow*)this)->m_bIconized = false;
863     return m_bIconized;
864 } // end of wxTopLevelWindowOS2::IsIconized
865 
Restore()866 void wxTopLevelWindowOS2::Restore()
867 {
868     DoShowWindow(SWP_RESTORE);
869 } // end of wxTopLevelWindowOS2::Restore
870 
871 // generate an artificial resize event
SendSizeEvent(int flags)872 void wxTopLevelWindowOS2::SendSizeEvent(int flags)
873 {
874     if (!m_bIconized)
875     {
876         RECTL                       vRect = wxGetWindowRect(GetHwnd());
877 
878         if ( flags & wxSEND_EVENT_POST )
879         {
880             (void)::WinPostMsg( m_hFrame
881                                ,WM_SIZE
882                                ,MPFROM2SHORT(vRect.xRight - vRect.xLeft, vRect.yTop - vRect.yBottom)
883                                ,MPFROM2SHORT(vRect.xRight - vRect.xLeft, vRect.yTop - vRect.yBottom)
884                               );
885         }
886         else // send it
887         {
888             (void)::WinSendMsg( m_hFrame
889                                ,WM_SIZE
890                                ,MPFROM2SHORT(vRect.xRight - vRect.xLeft, vRect.yTop - vRect.yBottom)
891                                ,MPFROM2SHORT(vRect.xRight - vRect.xLeft, vRect.yTop - vRect.yBottom)
892                               );
893         }
894     }
895 } // end of wxTopLevelWindowOS2::SendSizeEvent
896 
897 // ----------------------------------------------------------------------------
898 // wxTopLevelWindowOS2 fullscreen
899 // ----------------------------------------------------------------------------
900 
ShowFullScreen(bool bShow,long lStyle)901 bool wxTopLevelWindowOS2::ShowFullScreen( bool bShow,
902                                           long lStyle )
903 {
904     if (bShow)
905     {
906         if (IsFullScreen())
907             return false;
908 
909         m_bFsIsShowing = true;
910         m_lFsStyle = lStyle;
911 
912         //
913         // Zap the frame borders
914         //
915 
916         //
917         // Save the 'normal' window lStyle
918         //
919         m_lFsOldWindowStyle = ::WinQueryWindowULong( (HWND)GetHWND()
920                                                     ,QWL_STYLE
921                                                    );
922 
923         //
924         // Save the old position, width & height, maximize state
925         //
926         m_vFsOldSize = GetRect();
927         m_bFsIsMaximized = IsMaximized();
928 
929         //
930         // Decide which window lStyle flags to turn off
931         //
932         LONG lNewStyle = m_lFsOldWindowStyle;
933         LONG lOffFlags = 0;
934 
935         if (lStyle & wxFULLSCREEN_NOBORDER)
936             lOffFlags |= FCF_BORDER;
937         if (lStyle & wxFULLSCREEN_NOCAPTION)
938             lOffFlags |= (FCF_TASKLIST | FCF_SYSMENU);
939 
940         lNewStyle &= (~lOffFlags);
941 
942         //
943         // Change our window style to be compatible with full-screen mode
944         //
945         ::WinSetWindowULong( (HWND)GetHWND()
946                             ,QWL_STYLE
947                             ,lNewStyle
948                            );
949 
950         //
951         // Resize to the size of the desktop
952         //
953         int   nWidth;
954         int   nHeight;
955         RECTL vRect = wxGetWindowRect(HWND_DESKTOP);
956 
957         nWidth = vRect.xRight - vRect.xLeft;
958         nHeight = vRect.yTop - vRect.yBottom;
959 
960         SetSize( nWidth, nHeight );
961 
962         //
963         // Now flush the window style cache and actually go full-screen
964         //
965         ::WinSetWindowPos( m_hFrame
966                           ,HWND_TOP
967                           ,0
968                           ,0
969                           ,nWidth
970                           ,nHeight
971                           ,SWP_SIZE | SWP_MOVE
972                          );
973 
974         wxSize full( nWidth, nHeight );
975         wxSizeEvent vEvent( full, GetId() );
976         HandleWindowEvent(vEvent);
977         return true;
978     }
979     else
980     {
981         if (!IsFullScreen())
982             return false;
983 
984         m_bFsIsShowing = false;
985         Maximize(m_bFsIsMaximized);
986         ::WinSetWindowULong( (HWND)GetHWND()
987                             ,QWL_STYLE
988                             ,m_lFsOldWindowStyle
989                            );
990         ::WinSetWindowPos( m_hFrame
991                           ,HWND_TOP
992                           ,m_vFsOldSize.x
993                           ,m_vFsOldSize.y
994                           ,m_vFsOldSize.width
995                           ,m_vFsOldSize.height
996                           ,SWP_SIZE | SWP_MOVE
997                          );
998         return true;
999     }
1000 } // end of wxTopLevelWindowOS2::ShowFullScreen
1001 
1002 // ----------------------------------------------------------------------------
1003 // wxTopLevelWindowOS2 misc
1004 // ----------------------------------------------------------------------------
1005 
SetIcons(const wxIconBundle & rIcons)1006 void wxTopLevelWindowOS2::SetIcons(
1007   const wxIconBundle&               rIcons
1008 )
1009 {
1010     //
1011     // This sets m_icon
1012     //
1013     wxTopLevelWindowBase::SetIcons(rIcons);
1014 
1015     const wxIcon& vIcon = rIcons.GetIconOfExactSize(32);
1016 
1017     if (vIcon.IsOk())
1018     {
1019         ::WinSendMsg( m_hFrame
1020                      ,WM_SETICON
1021                      ,(MPARAM)((HPOINTER)vIcon.GetHICON())
1022                      ,NULL
1023                     );
1024         ::WinSendMsg( m_hFrame
1025                      ,WM_UPDATEFRAME
1026                      ,(MPARAM)FCF_ICON
1027                      ,(MPARAM)0
1028                     );
1029     }
1030 } // end of wxTopLevelWindowOS2::SetIcon
1031 
EnableCloseButton(bool bEnable)1032 bool wxTopLevelWindowOS2::EnableCloseButton( bool bEnable )
1033 {
1034     //
1035     // Get system (a.k.a. window) menu
1036     //
1037     HMENU hMenu = ::WinWindowFromID(m_hFrame, FID_SYSMENU);
1038 
1039     if (!hMenu)
1040     {
1041         wxLogLastError(wxT("GetSystemMenu"));
1042         return false;
1043     }
1044 
1045     //
1046     // Enabling/disabling the close item from it also automatically
1047     // disables/enables the close title bar button
1048     //
1049     if (bEnable)
1050         (void)::WinSendMsg( hMenu
1051                            ,MM_SETITEMATTR
1052                            ,MPFROM2SHORT(SC_CLOSE, FALSE)
1053                            ,MPFROM2SHORT(MIA_DISABLED, FALSE)
1054                           );
1055     else
1056         (void)::WinSendMsg( hMenu
1057                            ,MM_SETITEMATTR
1058                            ,MPFROM2SHORT(SC_CLOSE, FALSE)
1059                            ,MPFROM2SHORT(MIA_DISABLED, MIA_DISABLED)
1060                           );
1061 
1062     //
1063     // Update appearance immediately
1064     //
1065     ::WinSendMsg( m_hFrame
1066                  ,WM_UPDATEFRAME
1067                  ,(MPARAM)FCF_MENU
1068                  ,(MPARAM)0
1069                 );
1070     return true;
1071 } // end of wxTopLevelWindowOS2::EnableCloseButton
1072 
1073 // ============================================================================
1074 // wxTLWHiddenParentModule implementation
1075 // ============================================================================
1076 
1077 HWND          wxTLWHiddenParentModule::m_shWnd = NULL;
1078 const wxChar* wxTLWHiddenParentModule::m_szClassName = NULL;
1079 
OnInit()1080 bool wxTLWHiddenParentModule::OnInit()
1081 {
1082     m_shWnd = NULL;
1083     m_szClassName = NULL;
1084     return true;
1085 } // end of wxTLWHiddenParentModule::OnInit
1086 
OnExit()1087 void wxTLWHiddenParentModule::OnExit()
1088 {
1089     if (m_shWnd)
1090     {
1091         if (!::WinDestroyWindow(m_shWnd))
1092         {
1093             wxLogLastError(wxT("DestroyWindow(hidden TLW parent)"));
1094         }
1095         m_shWnd = NULL;
1096     }
1097 
1098     m_szClassName = NULL;
1099 } // end of wxTLWHiddenParentModule::OnExit
1100 
1101 /* static */
GetHWND()1102 HWND wxTLWHiddenParentModule::GetHWND()
1103 {
1104     if (!m_shWnd)
1105     {
1106         if (!m_szClassName)
1107         {
1108             static const wxChar*    zHIDDEN_PARENT_CLASS = wxT("wxTLWHiddenParent");
1109 
1110             if (!::WinRegisterClass( wxGetInstance()
1111                                     ,(PSZ)zHIDDEN_PARENT_CLASS
1112                                     ,NULL
1113                                     ,0
1114                                     ,sizeof(ULONG)
1115                                    ))
1116             {
1117                 wxLogLastError(wxT("RegisterClass(\"wxTLWHiddenParent\")"));
1118             }
1119             else
1120             {
1121                 m_szClassName = zHIDDEN_PARENT_CLASS;
1122             }
1123         }
1124         m_shWnd = ::WinCreateWindow( HWND_DESKTOP,
1125                                      (PSZ)m_szClassName,
1126                                      "",
1127                                      0L,
1128                                      (LONG)0L,
1129                                      (LONG)0L,
1130                                      (LONG)0L,
1131                                      (LONG)0L,
1132                                      NULLHANDLE,
1133                                      HWND_TOP,
1134                                      0L,
1135                                      NULL,
1136                                      NULL );
1137         if (!m_shWnd)
1138         {
1139             wxLogLastError(wxT("CreateWindow(hidden TLW parent)"));
1140         }
1141     }
1142     return m_shWnd;
1143 } // end of wxTLWHiddenParentModule::GetHWND
1144