1 /////////////////////////////////////////////////////////////////////////////// 
   2 // Name:        x11/toplevel.cpp 
   3 // Purpose:     implements wxTopLevelWindow for X11 
   4 // Author:      Julian Smart 
   8 // Copyright:   (c) 2002 Julian Smart 
   9 // License:     wxWindows licence 
  10 /////////////////////////////////////////////////////////////////////////////// 
  12 // ============================================================================ 
  14 // ============================================================================ 
  16 // ---------------------------------------------------------------------------- 
  18 // ---------------------------------------------------------------------------- 
  21     #pragma implementation "toplevel.h" 
  24 // For compilers that support precompilation, includes "wx.h". 
  25 #include "wx/wxprec.h" 
  33     #include "wx/toplevel.h" 
  34     #include "wx/string.h" 
  39     #include "wx/statusbr.h" 
  42 #include "wx/settings.h" 
  43 #include "wx/x11/private.h" 
  44 #include "X11/Xutil.h" 
  46 bool wxMWMIsRunning(Window w
); 
  48 // ---------------------------------------------------------------------------- 
  49 // wxTopLevelWindowX11 creation 
  50 // ---------------------------------------------------------------------------- 
  52 void wxTopLevelWindowX11::Init() 
  55     m_maximizeOnShow 
= FALSE
; 
  57     // unlike (almost?) all other windows, frames are created hidden 
  60     // Data to save/restore when calling ShowFullScreen 
  62     m_fsIsMaximized 
= FALSE
; 
  63     m_fsIsShowing 
= FALSE
; 
  68 bool wxTopLevelWindowX11::Create(wxWindow 
*parent
, 
  70                                  const wxString
& title
, 
  79     m_windowStyle 
= style
; 
  84     m_windowId 
= id 
== -1 ? NewControlId() : id
; 
  87         parent
->AddChild(this); 
  89     wxTopLevelWindows
.Append(this); 
  91     Display 
*xdisplay 
= wxGlobalDisplay(); 
  92     int xscreen 
= DefaultScreen( xdisplay 
); 
  93     Visual 
*xvisual 
= DefaultVisual( xdisplay
, xscreen 
); 
  94     Window xparent 
= RootWindow( xdisplay
, xscreen 
); 
  95     Colormap cm 
= DefaultColormap( xdisplay
, xscreen 
); 
  97     if (GetExtraStyle() & wxTOPLEVEL_EX_DIALOG
) 
  98         m_backgroundColour 
= wxSystemSettings::GetColour(wxSYS_COLOUR_BTNFACE
); 
 100         m_backgroundColour 
= wxSystemSettings::GetColour(wxSYS_COLOUR_APPWORKSPACE
); 
 101     m_backgroundColour
.CalcPixel( (WXColormap
) cm 
); 
 104     XSetWindowAttributes xattributes
; 
 105     XSizeHints size_hints
; 
 108     long xattributes_mask 
= 
 110         CWBorderPixel 
| CWBackPixel
; 
 111     xattributes
.background_pixel 
= m_backgroundColour
.GetPixel(); 
 112     xattributes
.border_pixel 
= BlackPixel( xdisplay
, xscreen 
); 
 114     // TODO: if we want no border, caption etc., 
 115     // I think we set this to True to remove decorations 
 117     xattributes
.override_redirect 
= False
; 
 131     Window xwindow 
= XCreateWindow( xdisplay
, xparent
, pos2
.x
, pos2
.y
, size2
.x
, size2
.y
,  
 132        0, DefaultDepth(xdisplay
,xscreen
), InputOutput
, xvisual
, xattributes_mask
, &xattributes 
); 
 133     m_mainWidget 
= (WXWindow
) xwindow
; 
 135     XSelectInput( xdisplay
, xwindow
, 
 137         GR_EVENT_MASK_CLOSE_REQ 
| 
 139         ExposureMask 
| KeyPressMask 
| KeyReleaseMask 
| ButtonPressMask 
| ButtonReleaseMask 
| 
 140         ButtonMotionMask 
| EnterWindowMask 
| LeaveWindowMask 
| PointerMotionMask 
| 
 141         KeymapStateMask 
| FocusChangeMask 
| ColormapChangeMask 
| StructureNotifyMask 
| 
 142         PropertyChangeMask 
); 
 144     wxAddWindowToTable( xwindow
, (wxWindow
*) this ); 
 146     // Set background to None which will prevent X11 from clearing the 
 147     // background completely. 
 148     XSetWindowBackgroundPixmap( xdisplay
, xwindow
, None 
); 
 150     if (GetExtraStyle() & wxTOPLEVEL_EX_DIALOG
) 
 152         if (GetParent() && GetParent()->GetMainWindow()) 
 154              Window xparentwindow 
= (Window
) GetParent()->GetMainWindow(); 
 155              XSetTransientForHint( xdisplay
, xwindow
, xparentwindow 
); 
 159     size_hints
.flags 
= PSize 
| PPosition
; 
 160     size_hints
.x 
= pos2
.x
; 
 161     size_hints
.y 
= pos2
.y
; 
 162     size_hints
.width 
= size2
.x
; 
 163     size_hints
.height 
= size2
.y
; 
 164     XSetWMNormalHints( xdisplay
, xwindow
, &size_hints
); 
 166     wm_hints
.flags 
= InputHint 
| StateHint 
/* | WindowGroupHint */; 
 167     wm_hints
.input 
= True
; 
 168     wm_hints
.initial_state 
= NormalState
; 
 169     XSetWMHints( xdisplay
, xwindow
, &wm_hints
); 
 171     Atom wm_protocols
[2]; 
 172     wm_protocols
[0] = XInternAtom( xdisplay
, "WM_DELETE_WINDOW", False 
); 
 173     wm_protocols
[1] = XInternAtom( xdisplay
, "WM_TAKE_FOCUS", False 
); 
 174     XSetWMProtocols( xdisplay
, xwindow
, wm_protocols
, 2); 
 176     wxSetWMDecorations( xwindow
, style
); 
 183 wxTopLevelWindowX11::~wxTopLevelWindowX11() 
 185     wxTopLevelWindows
.DeleteObject(this); 
 187     // If this is the last top-level window, exit. 
 188     if ( wxTheApp 
&& (wxTopLevelWindows
.Number() == 0) ) 
 190         wxTheApp
->SetTopWindow(NULL
); 
 192         if (wxTheApp
->GetExitOnFrameDelete()) 
 194             // Signal to the app that we're going to close 
 195             wxTheApp
->ExitMainLoop(); 
 200 // ---------------------------------------------------------------------------- 
 201 // wxTopLevelWindowX11 showing 
 202 // ---------------------------------------------------------------------------- 
 204 bool wxTopLevelWindowX11::Show(bool show
) 
 206     return wxWindowX11::Show(show
); 
 209 // ---------------------------------------------------------------------------- 
 210 // wxTopLevelWindowX11 maximize/minimize 
 211 // ---------------------------------------------------------------------------- 
 213 void wxTopLevelWindowX11::Maximize(bool maximize
) 
 218 bool wxTopLevelWindowX11::IsMaximized() const 
 224 void wxTopLevelWindowX11::Iconize(bool iconize
) 
 226     if (!m_iconized 
&& GetMainWindow()) 
 228         if (XIconifyWindow(wxGlobalDisplay(), 
 229             (Window
) GetMainWindow(), DefaultScreen(wxGlobalDisplay())) != 0) 
 234 bool wxTopLevelWindowX11::IsIconized() const 
 239 void wxTopLevelWindowX11::Restore() 
 241     // This is the way to deiconify the window, according to the X FAQ 
 242     if (m_iconized 
&& GetMainWindow()) 
 244         XMapWindow(wxGlobalDisplay(), (Window
) GetMainWindow()); 
 249 // ---------------------------------------------------------------------------- 
 250 // wxTopLevelWindowX11 fullscreen 
 251 // ---------------------------------------------------------------------------- 
 253 bool wxTopLevelWindowX11::ShowFullScreen(bool show
, long style
) 
 260         m_fsIsShowing 
= TRUE
; 
 272         m_fsIsShowing 
= FALSE
; 
 279 // ---------------------------------------------------------------------------- 
 280 // wxTopLevelWindowX11 misc 
 281 // ---------------------------------------------------------------------------- 
 283 void wxTopLevelWindowX11::SetIcon(const wxIcon
& icon
) 
 286     wxTopLevelWindowBase::SetIcon(icon
); 
 288     if (icon
.Ok() && GetMainWindow()) 
 290         XWMHints 
*wmHints 
= XAllocWMHints(); 
 291         wmHints
->icon_pixmap 
= (Pixmap
) icon
.GetPixmap(); 
 293         wmHints
->flags 
= IconPixmapHint
; 
 297             wmHints
->flags 
|= IconMaskHint
; 
 298             wmHints
->icon_mask 
= (Pixmap
) icon
.GetMask()->GetBitmap(); 
 301         XSetWMHints(wxGlobalDisplay(), (Window
) GetMainWindow(), wmHints
); 
 306 void wxTopLevelWindowX11::SetTitle(const wxString
& title
) 
 311         XStoreName(wxGlobalDisplay(), (Window
) GetMainWindow(), 
 312             (const char*) title
); 
 313         XSetIconName(wxGlobalDisplay(), (Window
) GetMainWindow(), 
 314             (const char*) title
); 
 316         // Use this if the platform doesn't supply the above functions. 
 318         XTextProperty textProperty
; 
 319         textProperty
.value 
= (unsigned char*) title
; 
 320         textProperty
.encoding 
= XA_STRING
; 
 321         textProperty
.format 
= 8; 
 322         textProperty
.nitems 
= 1; 
 324         XSetTextProperty(wxGlobalDisplay(), (Window
) GetMainWindow(), 
 325             & textProperty
, WM_NAME
); 
 330 wxString 
wxTopLevelWindowX11::GetTitle() const 
 335 #ifndef MWM_DECOR_BORDER 
 336 /* bit definitions for MwmHints.flags */ 
 337 #define MWM_HINTS_FUNCTIONS (1L << 0) 
 338 #define MWM_HINTS_DECORATIONS (1L << 1) 
 339 #define MWM_HINTS_INPUT_MODE (1L << 2) 
 340 #define MWM_HINTS_STATUS (1L << 3) 
 342 #define MWM_DECOR_ALL           (1L << 0) 
 343 #define MWM_DECOR_BORDER        (1L << 1) 
 344 #define MWM_DECOR_RESIZEH       (1L << 2) 
 345 #define MWM_DECOR_TITLE         (1L << 3) 
 346 #define MWM_DECOR_MENU          (1L << 4) 
 347 #define MWM_DECOR_MINIMIZE      (1L << 5) 
 348 #define MWM_DECOR_MAXIMIZE      (1L << 6) 
 358 #define PROP_MOTIF_WM_HINTS_ELEMENTS 5 
 360 // Set the window manager decorations according to the 
 361 // given wxWindows style 
 362 bool wxSetWMDecorations(Window w
, long style
) 
 364     if (!wxMWMIsRunning(w
)) 
 367     Atom mwm_wm_hints 
= XInternAtom(wxGlobalDisplay(),"_MOTIF_WM_HINTS", False
); 
 370     hints
.decorations 
= 0; 
 372     if (style 
& wxRESIZE_BORDER
) 
 374         wxLogDebug("MWM_DECOR_RESIZEH"); 
 375         hints
.flags 
|= MWM_HINTS_DECORATIONS
; 
 376         hints
.decorations 
|= MWM_DECOR_RESIZEH
; 
 379     if (style 
& wxSYSTEM_MENU
) 
 381         wxLogDebug("MWM_DECOR_MENU"); 
 382         hints
.flags 
|= MWM_HINTS_DECORATIONS
; 
 383         hints
.decorations 
|= MWM_DECOR_MENU
; 
 386     if ((style 
& wxCAPTION
) || 
 387         (style 
& wxTINY_CAPTION_HORIZ
) || 
 388         (style 
& wxTINY_CAPTION_VERT
)) 
 390         wxLogDebug("MWM_DECOR_TITLE"); 
 391         hints
.flags 
|= MWM_HINTS_DECORATIONS
; 
 392         hints
.decorations 
|= MWM_DECOR_TITLE
; 
 395     if ((style 
& wxTHICK_FRAME
) || (style 
& wxSIMPLE_BORDER
) || (style 
& wxCAPTION
)) 
 397         wxLogDebug("MWM_DECOR_BORDER"); 
 398         hints
.flags 
|= MWM_HINTS_DECORATIONS
; 
 399         hints
.decorations 
|= MWM_DECOR_BORDER
; 
 402     if (style 
& wxMINIMIZE_BOX
) 
 404         wxLogDebug("MWM_DECOR_MINIMIZE"); 
 405         hints
.flags 
|= MWM_HINTS_DECORATIONS
; 
 406         hints
.decorations 
|= MWM_DECOR_MINIMIZE
; 
 409     if (style 
& wxMAXIMIZE_BOX
) 
 411         wxLogDebug("MWM_DECOR_MAXIMIZE"); 
 412         hints
.flags 
|= MWM_HINTS_DECORATIONS
; 
 413         hints
.decorations 
|= MWM_DECOR_MAXIMIZE
; 
 416     XChangeProperty(wxGlobalDisplay(), 
 418                     mwm_wm_hints
, mwm_wm_hints
, 
 420                     (unsigned char *) &hints
, PROP_MOTIF_WM_HINTS_ELEMENTS
); 
 425 bool wxMWMIsRunning(Window w
) 
 427     Display 
*dpy 
= (Display
*)wxGetDisplay(); 
 428     Atom motifWmInfo 
= XInternAtom(dpy
, "_MOTIF_WM_INFO", False
); 
 430     unsigned long length
, bytesafter
; 
 431     unsigned char value
[20]; 
 432     unsigned char *ptr 
= &value
[0]; 
 436     type 
= format 
= length 
= 0; 
 439     ret 
= XGetWindowProperty(wxGlobalDisplay(), w
, motifWmInfo
, 
 440             0L, 2, False
, motifWmInfo
,  
 441             &type
, &format
, &length
, &bytesafter
, &ptr
); 
 443     return (ret 
== Success
); 
 446 // For implementation purposes - sometimes decorations make the client area 
 448 wxPoint 
wxTopLevelWindowX11::GetClientAreaOrigin() const 
 450     // In fact wxFrame::GetClientAreaOrigin 
 451     // does the required calculation already. 
 453     if (this->IsKindOf(CLASSINFO(wxFrame
))) 
 455         wxFrame
* frame 
= (wxFrame
*) this; 
 456         if (frame
->GetMenuBar()) 
 457             return wxPoint(0, frame
->GetMenuBar()->GetSize().y
); 
 460     return wxPoint(0, 0); 
 463 void wxTopLevelWindowX11::DoGetClientSize( int *width
, int *height 
) const 
 465     wxWindowX11::DoGetClientSize(width
, height
); 
 466     // Done by wxTopLevelWindow 
 468     if (this->IsKindOf(CLASSINFO(wxFrame
))) 
 470         wxFrame
* frame 
= (wxFrame
*) this; 
 471         if (frame
->GetMenuBar()) 
 472             (*height
) -= frame
->GetMenuBar()->GetSize().y
; 
 473         if (frame
->GetStatusBar()) 
 474             (*height
) -= frame
->GetStatusBar()->GetSize().y
; 
 479 void wxTopLevelWindowX11::DoSetClientSize(int width
, int height
) 
 481     wxWindowX11::DoSetClientSize(width
, height
); 
 484     if (!GetMainWindow()) 
 487     XWindowChanges windowChanges
; 
 492         windowChanges
.width 
= width 
; 
 493         valueMask 
|= CWWidth
; 
 497         windowChanges
.height 
= height 
; 
 498         valueMask 
|= CWHeight
; 
 500     XConfigureWindow(wxGlobalDisplay(), (Window
) GetMainWindow(), 
 501         valueMask
, & windowChanges
); 
 505 void wxTopLevelWindowX11::DoSetSize(int x
, int y
, int width
, int height
, int sizeFlags
) 
 508     msg
.Printf("Setting pos: %d, %d", x
, y
); 
 510     wxWindowX11::DoSetSize(x
, y
, width
, height
, sizeFlags
); 
 512     wxPoint pt 
= GetPosition(); 
 513     msg
.Printf("After, pos: %d, %d", pt
.x
, pt
.y
); 
 516     XSync(wxGlobalDisplay(), False
); 
 520     msg
.Printf("Before setting size: %d, %d", w
, h
); 
 522     if (!GetMainWindow()) 
 525     XWindowChanges windowChanges
; 
 528     if (x 
!= -1 || (sizeFlags 
& wxSIZE_ALLOW_MINUS_ONE
)) 
 531         AdjustForParentClientOrigin( x
, yy
, sizeFlags
); 
 535     if (y 
!= -1 || (sizeFlags 
& wxSIZE_ALLOW_MINUS_ONE
)) 
 538         AdjustForParentClientOrigin( xx
, y
, sizeFlags
); 
 542     if (width 
!= -1 || (sizeFlags 
& wxSIZE_ALLOW_MINUS_ONE
)) 
 544         windowChanges
.width 
= width 
/* - m_borderSize*2 */; 
 545         valueMask 
|= CWWidth
; 
 547     if (height 
!= -1 || (sizeFlags 
& wxSIZE_ALLOW_MINUS_ONE
)) 
 549         windowChanges
.height 
= height 
/* -m_borderSize*2*/; 
 550         valueMask 
|= CWHeight
; 
 553     XConfigureWindow(wxGlobalDisplay(), (Window
) GetMainWindow(), 
 554                      valueMask
, & windowChanges
); 
 555     XSync(wxGlobalDisplay(), False
); 
 557     msg
.Printf("Tried to set to %d, %d. After setting size: %d, %d", width
, height
, w
, h
); 
 562 void wxTopLevelWindowX11::DoGetPosition(int *x
, int *y
) const 
 564     XSync(wxGlobalDisplay(), False
); 
 565     Window window 
= (Window
) m_mainWidget
; 
 571         wxLogDebug("Translating..."); 
 573         XTranslateCoordinates(wxGlobalDisplay(), window
, XDefaultRootWindow(wxGlobalDisplay()), 
 574                                   0, 0, & offsetX
, & offsetY
, & childWindow
); 
 577         msg
.Printf("Offset: %d, %d", offsetX
, offsetY
); 
 580         XWindowAttributes attr
; 
 581         Status status 
= XGetWindowAttributes(wxGlobalDisplay(), window
, & attr
); 
 586             *x 
= attr
.x 
+ offsetX
; 
 587             *y 
= attr
.y 
+ offsetY
;