1 ///////////////////////////////////////////////////////////////////////////// 
   2 // Name:        src/mgl/window.cpp 
   4 // Author:      Vaclav Slavik 
   5 //              (based on GTK & MSW implementations) 
   7 // Copyright:   (c) 2001-2002 SciTech Software, Inc. (www.scitechsoft.com) 
   8 // Licence:     wxWindows licence 
   9 ///////////////////////////////////////////////////////////////////////////// 
  11 // =========================================================================== 
  13 // =========================================================================== 
  15 // --------------------------------------------------------------------------- 
  17 // --------------------------------------------------------------------------- 
  19 // For compilers that support precompilation, includes "wx.h". 
  20 #include "wx/wxprec.h" 
  26 #include "wx/window.h" 
  29     #include "wx/msgdlg.h" 
  32     #include "wx/dcclient.h" 
  38     #include "wx/dcscreen.h" 
  42 #if wxUSE_DRAG_AND_DROP 
  46 #include "wx/sysopt.h" 
  47 #include "wx/mgl/private.h" 
  53     #include "wx/tooltip.h" 
  56 // --------------------------------------------------------------------------- 
  58 // --------------------------------------------------------------------------- 
  60 // MGL window manager and associated DC. 
  61 winmng_t 
*g_winMng 
= NULL
; 
  62 MGLDevCtx 
*g_displayDC 
= NULL
; 
  64 // the window that has keyboard focus: 
  65 static wxWindowMGL 
*gs_focusedWindow 
= NULL
; 
  66 // the window that is about to be focused after currently focused 
  68 static wxWindow 
*gs_toBeFocusedWindow 
= NULL
; 
  69 // the window that is currently under mouse cursor: 
  70 static wxWindowMGL 
*gs_windowUnderMouse 
= NULL
; 
  71 // the window that has mouse capture 
  72 static wxWindowMGL 
*gs_mouseCapture 
= NULL
; 
  73 // the frame that is currently active (i.e. its child has focus). It is 
  74 // used to generate wxActivateEvents 
  75 static wxWindowMGL 
*gs_activeFrame 
= NULL
; 
  76 // track the mouse button state for wxGetMouseState() 
  77 unsigned long g_buttonState 
= 0; 
  79 // --------------------------------------------------------------------------- 
  81 // --------------------------------------------------------------------------- 
  83 // Custom identifiers used to distinguish between various event handlers 
  84 // and capture handlers passed to MGL_wm 
  87     wxMGL_CAPTURE_MOUSE 
= 1, 
  88     wxMGL_CAPTURE_KEYB  
= 2 
  92 // --------------------------------------------------------------------------- 
  94 // --------------------------------------------------------------------------- 
  96 // Returns toplevel grandparent of given window: 
  97 static wxWindowMGL
* wxGetTopLevelParent(wxWindowMGL 
*win
) 
 100     while (p 
&& !p
->IsTopLevel()) 
 105 // An easy way to capture screenshots: 
 106 static void wxCaptureScreenshot(bool activeWindowOnly
) 
 109     #define SCREENSHOT_FILENAME _T("sshot%03i.png") 
 111     #define SCREENSHOT_FILENAME _T("screenshot-%03i.png") 
 113     static int screenshot_num 
= 0; 
 118         screenshot
.Printf(SCREENSHOT_FILENAME
, screenshot_num
++); 
 119     } while ( wxFileExists(screenshot
) && screenshot_num 
< 1000 ); 
 121     wxRect 
r(0, 0, g_displayDC
->sizex(), g_displayDC
->sizey()); 
 123     if ( activeWindowOnly 
&& gs_activeFrame 
) 
 125         r
.Intersect(gs_activeFrame
->GetRect()); 
 128     g_displayDC
->savePNGFromDC(screenshot
.mb_str(), 
 129                                r
.x
, r
. y
, r
.x
+r
.width
, r
.y
+r
.height
); 
 131     wxMessageBox(wxString::Format(_T("Screenshot captured: %s"), 
 132                                   screenshot
.c_str())); 
 135 // --------------------------------------------------------------------------- 
 137 // --------------------------------------------------------------------------- 
 139 static void MGLAPI 
wxWindowPainter(window_t 
*wnd
, MGLDC 
*dc
) 
 141     wxWindowMGL 
*w 
= (wxWindow
*) wnd
->userData
; 
 143     if ( w 
&& !(w
->GetWindowStyle() & wxTRANSPARENT_WINDOW
) ) 
 146         w
->HandlePaint(&ctx
); 
 150 static ibool MGLAPI 
wxWindowMouseHandler(window_t 
*wnd
, event_t 
*e
) 
 152     wxWindowMGL 
*win 
= (wxWindowMGL
*)MGL_wmGetWindowUserData(wnd
); 
 153     wxPoint 
orig(win
->GetClientAreaOrigin()); 
 156     g_buttonState 
= e
->modifiers
; 
 158     MGL_wmCoordGlobalToLocal(win
->GetHandle(), 
 159                              e
->where_x
, e
->where_y
, &where
.x
, &where
.y
); 
 161     for (wxWindowMGL 
*w 
= win
; w
; w 
= w
->GetParent()) 
 163         if ( !w
->IsEnabled() ) 
 165         if ( w
->IsTopLevel() ) 
 169     wxEventType type 
= wxEVT_NULL
; 
 171     event
.SetEventObject(win
); 
 172     event
.SetTimestamp(e
->when
); 
 173     event
.m_x 
= where
.x 
- orig
.x
; 
 174     event
.m_y 
= where
.y 
- orig
.y
; 
 175     event
.m_shiftDown 
= ( e
->modifiers 
& EVT_SHIFTKEY 
) != 0; 
 176     event
.m_controlDown 
= ( e
->modifiers 
& EVT_CTRLSTATE 
) != 0; 
 177     event
.m_altDown 
= ( e
->modifiers 
& EVT_LEFTALT 
) != 0; 
 178     event
.m_metaDown 
= ( e
->modifiers 
& EVT_RIGHTALT 
) != 0; 
 179     event
.m_leftDown 
= ( e
->modifiers 
& EVT_LEFTBUT 
) != 0; 
 180     event
.m_middleDown 
= ( e
->modifiers 
& EVT_MIDDLEBUT 
) != 0; 
 181     event
.m_rightDown 
= ( e
->modifiers 
& EVT_RIGHTBUT 
) != 0; 
 186             // Change focus if the user clicks outside focused window: 
 187             if ( win
->AcceptsFocus() && wxWindow::FindFocus() != win 
) 
 190             if ( e
->message 
& EVT_DBLCLICK 
) 
 192                 if ( e
->message 
& EVT_LEFTBMASK 
) 
 193                     type 
= wxEVT_LEFT_DCLICK
; 
 194                 else if ( e
->message 
& EVT_MIDDLEBMASK 
) 
 195                     type 
= wxEVT_MIDDLE_DCLICK
; 
 196                 else if ( e
->message 
& EVT_RIGHTBMASK 
) 
 197                     type 
= wxEVT_RIGHT_DCLICK
; 
 201                 if ( e
->message 
& EVT_LEFTBMASK 
) 
 202                     type 
= wxEVT_LEFT_DOWN
; 
 203                 else if ( e
->message 
& EVT_MIDDLEBMASK 
) 
 204                     type 
= wxEVT_MIDDLE_DOWN
; 
 205                 else if ( e
->message 
& EVT_RIGHTBMASK 
) 
 206                     type 
= wxEVT_RIGHT_DOWN
; 
 212             if ( e
->message 
& EVT_LEFTBMASK 
) 
 213                 type 
= wxEVT_LEFT_UP
; 
 214             else if ( e
->message 
& EVT_MIDDLEBMASK 
) 
 215                 type 
= wxEVT_MIDDLE_UP
; 
 216             else if ( e
->message 
& EVT_RIGHTBMASK 
) 
 217                 type 
= wxEVT_RIGHT_UP
; 
 221             if ( !gs_mouseCapture 
) 
 223                 if ( win 
!= gs_windowUnderMouse 
) 
 225                     if ( gs_windowUnderMouse 
) 
 227                         wxMouseEvent 
event2(event
); 
 228                         MGL_wmCoordGlobalToLocal(gs_windowUnderMouse
->GetHandle(), 
 229                                                  e
->where_x
, e
->where_y
, 
 230                                                  &event2
.m_x
, &event2
.m_y
); 
 232                         wxPoint 
orig(gs_windowUnderMouse
->GetClientAreaOrigin()); 
 233                         event2
.m_x 
-= orig
.x
; 
 234                         event2
.m_y 
-= orig
.y
; 
 236                         event2
.SetEventObject(gs_windowUnderMouse
); 
 237                         event2
.SetEventType(wxEVT_LEAVE_WINDOW
); 
 238                         gs_windowUnderMouse
->GetEventHandler()->ProcessEvent(event2
); 
 241                     wxMouseEvent 
event3(event
); 
 242                     event3
.SetEventType(wxEVT_ENTER_WINDOW
); 
 243                     win
->GetEventHandler()->ProcessEvent(event3
); 
 245                     gs_windowUnderMouse 
= win
; 
 248             else // gs_mouseCapture 
 250                 bool inside 
= (where
.x 
>= 0 && 
 252                                where
.x 
< win
->GetSize().x 
&& 
 253                                where
.y 
< win
->GetSize().y
); 
 254                 if ( (inside 
&& gs_windowUnderMouse 
!= win
) || 
 255                      (!inside 
&& gs_windowUnderMouse 
== win
) ) 
 257                     wxMouseEvent 
evt(inside 
? 
 258                                      wxEVT_ENTER_WINDOW 
: wxEVT_LEAVE_WINDOW
); 
 259                     evt
.SetEventObject(win
); 
 260                     win
->GetEventHandler()->ProcessEvent(evt
); 
 261                     gs_windowUnderMouse 
= inside 
? win 
: NULL
; 
 272     if ( type 
== wxEVT_NULL 
) 
 278         event
.SetEventType(type
); 
 279         return win
->GetEventHandler()->ProcessEvent(event
); 
 283 static long wxScanToKeyCode(event_t 
*event
, bool translate
) 
 285     // VS: make it __WXDEBUG__-only, since we have lots of wxLogTrace calls 
 286     //     here and the arguments would be stored in non-debug executable even 
 287     //     though wxLogTrace would be no-op... 
 289       #define KEY(mgl_key,wx_key) \ 
 291           wxLogTrace(_T("keyevents"), \ 
 292                      _T("key " #mgl_key ", mapped to " #wx_key)); \ 
 296       #define KEY(mgl_key,wx_key) \ 
 297         case mgl_key: key = wx_key; break; 
 304         bool numlock 
= (event
->modifiers 
& EVT_NUMLOCK
) != 0; 
 306         switch ( EVT_scanCode(event
->message
) ) 
 308             KEY (KB_padMinus
,       WXK_NUMPAD_SUBTRACT
) 
 309             KEY (KB_padPlus
,        WXK_NUMPAD_ADD
) 
 310             KEY (KB_padTimes
,       WXK_NUMPAD_MULTIPLY
) 
 311             KEY (KB_padDivide
,      WXK_NUMPAD_DIVIDE
) 
 312             KEY (KB_padCenter
,      numlock 
? WXK_NUMPAD5 
: WXK_NUMPAD_SEPARATOR
) // ? 
 313             KEY (KB_padLeft
,        numlock 
? WXK_NUMPAD4 
: WXK_NUMPAD_LEFT
) 
 314             KEY (KB_padRight
,       numlock 
? WXK_NUMPAD6 
: WXK_NUMPAD_RIGHT
) 
 315             KEY (KB_padUp
,          numlock 
? WXK_NUMPAD8 
: WXK_NUMPAD_UP
) 
 316             KEY (KB_padDown
,        numlock 
? WXK_NUMPAD2 
: WXK_NUMPAD_DOWN
) 
 317             KEY (KB_padInsert
,      numlock 
? WXK_NUMPAD0 
: WXK_NUMPAD_INSERT
) 
 318             KEY (KB_padDelete
,      numlock 
? WXK_DECIMAL 
: WXK_NUMPAD_DELETE
) 
 319             KEY (KB_padHome
,        numlock 
? WXK_NUMPAD7 
: WXK_NUMPAD_HOME
) 
 320             KEY (KB_padEnd
,         numlock 
? WXK_NUMPAD1 
: WXK_NUMPAD_END
) 
 321             KEY (KB_padPageUp
,      numlock 
? WXK_NUMPAD9 
: WXK_NUMPAD_PAGEUP
) 
 322             KEY (KB_padPageDown
,    numlock 
? WXK_NUMPAD3 
: WXK_NUMPAD_PAGEDOWN
) 
 333             KEY (KB_minus
,          WXK_SUBTRACT
) 
 334             KEY (KB_equals
,         WXK_ADD
) 
 335             KEY (KB_backSlash
,      '\\') 
 346             KEY (KB_leftSquareBrace
,'[') 
 347             KEY (KB_rightSquareBrace
,']') 
 357             KEY (KB_semicolon
,      ';') 
 358             KEY (KB_apostrophe
,     '\'') 
 368             KEY (KB_divide
,         WXK_DIVIDE
) 
 369             KEY (KB_space
,          WXK_SPACE
) 
 378         switch ( EVT_scanCode(event
->message
) ) 
 380             KEY (KB_padEnter
,       WXK_NUMPAD_ENTER
) 
 390             KEY (KB_F10
,            WXK_F10
) 
 391             KEY (KB_F11
,            WXK_F11
) 
 392             KEY (KB_F12
,            WXK_F12
) 
 393             KEY (KB_left
,           WXK_LEFT
) 
 394             KEY (KB_right
,          WXK_RIGHT
) 
 396             KEY (KB_down
,           WXK_DOWN
) 
 397             KEY (KB_insert
,         WXK_INSERT
) 
 398             KEY (KB_delete
,         WXK_DELETE
) 
 399             KEY (KB_home
,           WXK_HOME
) 
 400             KEY (KB_end
,            WXK_END
) 
 401             KEY (KB_pageUp
,         WXK_PAGEUP
) 
 402             KEY (KB_pageDown
,       WXK_PAGEDOWN
) 
 403             KEY (KB_capsLock
,       WXK_CAPITAL
) 
 404             KEY (KB_numLock
,        WXK_NUMLOCK
) 
 405             KEY (KB_scrollLock
,     WXK_SCROLL
) 
 406             KEY (KB_leftShift
,      WXK_SHIFT
) 
 407             KEY (KB_rightShift
,     WXK_SHIFT
) 
 408             KEY (KB_leftCtrl
,       WXK_CONTROL
) 
 409             KEY (KB_rightCtrl
,      WXK_CONTROL
) 
 410             KEY (KB_leftAlt
,        WXK_ALT
) 
 411             KEY (KB_rightAlt
,       WXK_ALT
) 
 412             KEY (KB_leftWindows
,    WXK_START
) 
 413             KEY (KB_rightWindows
,   WXK_START
) 
 414             KEY (KB_menu
,           WXK_MENU
) 
 415             KEY (KB_sysReq
,         WXK_SNAPSHOT
) 
 416             KEY (KB_esc
,            WXK_ESCAPE
) 
 417             KEY (KB_backspace
,      WXK_BACK
) 
 418             KEY (KB_tab
,            WXK_TAB
) 
 419             KEY (KB_enter
,          WXK_RETURN
) 
 422                 key 
= EVT_asciiCode(event
->message
); 
 432 static bool wxHandleSpecialKeys(wxKeyEvent
& event
) 
 434     // Add an easy way to capture screenshots: 
 435     if ( event
.m_keyCode 
== WXK_SNAPSHOT
 
 436     #ifdef __WXDEBUG__ // FIXME_MGL - remove when KB_sysReq works in MGL! 
 437          || (event
.m_keyCode 
== WXK_F1 
&& 
 438             event
.m_shiftDown 
&& event
.m_controlDown
) 
 442         wxCaptureScreenshot(event
.m_altDown
/*only active wnd?*/); 
 449 static ibool MGLAPI 
wxWindowKeybHandler(window_t 
*wnd
, event_t 
*e
) 
 451     wxWindowMGL 
*win 
= (wxWindowMGL
*)MGL_wmGetWindowUserData(wnd
); 
 453     if ( !win
->IsEnabled() ) return FALSE
; 
 456     MGL_wmCoordGlobalToLocal(win
->GetHandle(), 
 457                              e
->where_x
, e
->where_y
, &where
.x
, &where
.y
); 
 460     event
.SetEventObject(win
); 
 461     event
.SetTimestamp(e
->when
); 
 462     event
.m_keyCode 
= wxScanToKeyCode(e
, true); 
 463     event
.m_scanCode 
= 0; // not used by wx at all 
 466     event
.m_shiftDown 
= ( e
->modifiers 
& EVT_SHIFTKEY 
) != 0; 
 467     event
.m_controlDown 
= ( e
->modifiers 
& EVT_CTRLSTATE 
) != 0; 
 468     event
.m_altDown 
= ( e
->modifiers 
& EVT_LEFTALT 
) != 0; 
 469     event
.m_metaDown 
= ( e
->modifiers 
& EVT_RIGHTALT 
) != 0; 
 471     if ( e
->what 
== EVT_KEYUP 
) 
 473         event
.SetEventType(wxEVT_KEY_UP
); 
 474         return win
->GetEventHandler()->ProcessEvent(event
); 
 481         event
.SetEventType(wxEVT_KEY_DOWN
); 
 484         ret 
= win
->GetEventHandler()->ProcessEvent(event
); 
 486         // wxMSW doesn't send char events with Alt pressed 
 487         // Only send wxEVT_CHAR event if not processed yet. Thus, ALT-x 
 488         // will only be sent if it is not in an accelerator table: 
 489         event2
.m_keyCode 
= wxScanToKeyCode(e
, false); 
 490         if ( !ret 
&& event2
.m_keyCode 
!= 0 ) 
 492             event2
.SetEventType(wxEVT_CHAR
); 
 493             ret 
= win
->GetEventHandler()->ProcessEvent(event2
); 
 496         // Synthetize navigation key event, but do it only if the TAB key 
 497         // wasn't handled yet: 
 498         if ( !ret 
&& event
.m_keyCode 
== WXK_TAB 
&& 
 499              win
->GetParent() && win
->GetParent()->HasFlag(wxTAB_TRAVERSAL
) ) 
 501             wxNavigationKeyEvent navEvent
; 
 502             navEvent
.SetEventObject(win
->GetParent()); 
 503             // Shift-TAB goes in reverse direction: 
 504             navEvent
.SetDirection(!event
.m_shiftDown
); 
 505             // Ctrl-TAB changes the (parent) window, i.e. switch notebook page: 
 506             navEvent
.SetWindowChange(event
.m_controlDown
); 
 507             navEvent
.SetCurrentFocus(wxStaticCast(win
, wxWindow
)); 
 508             ret 
= win
->GetParent()->GetEventHandler()->ProcessEvent(navEvent
); 
 511         // Finally, process special meaning keys that are usually 
 512         // a responsibility of OS or window manager: 
 514             ret 
= wxHandleSpecialKeys(event
); 
 520 // --------------------------------------------------------------------------- 
 522 // --------------------------------------------------------------------------- 
 524 // in wxUniv this class is abstract because it doesn't have DoPopupMenu() 
 525 IMPLEMENT_ABSTRACT_CLASS(wxWindowMGL
, wxWindowBase
) 
 527 BEGIN_EVENT_TABLE(wxWindowMGL
, wxWindowBase
) 
 530 // =========================================================================== 
 532 // =========================================================================== 
 534 // ---------------------------------------------------------------------------- 
 535 // constructors and such 
 536 // ---------------------------------------------------------------------------- 
 538 extern wxVideoMode 
wxGetDefaultDisplayMode(); 
 540 void wxWindowMGL::Init() 
 542     // First of all, make sure window manager is up and running. If it is 
 543     // not the case, initialize it in default display mode 
 546         if ( !wxTheApp
->SetDisplayMode(wxGetDefaultDisplayMode()) ) 
 547             wxLogFatalError(_("Cannot initialize display.")); 
 555     m_eraseBackground 
= -1; 
 559 wxWindowMGL::~wxWindowMGL() 
 563     m_isBeingDeleted 
= true; 
 565     if ( gs_mouseCapture 
== this ) 
 568     if (gs_activeFrame 
== this) 
 570         gs_activeFrame 
= NULL
; 
 571         // activate next frame in Z-order: 
 574             wxWindowMGL 
*win 
= (wxWindowMGL
*)m_wnd
->prev
->userData
; 
 577         else if ( m_wnd
->next 
) 
 579             wxWindowMGL 
*win 
= (wxWindowMGL
*)m_wnd
->next
->userData
; 
 584     if ( gs_focusedWindow 
== this ) 
 587     if ( gs_windowUnderMouse 
== this ) 
 588         gs_windowUnderMouse 
= NULL
; 
 593         MGL_wmDestroyWindow(m_wnd
); 
 596 // real construction (Init() must have been called before!) 
 597 bool wxWindowMGL::Create(wxWindow 
*parent
, 
 602                          const wxString
& name
) 
 604     if ( !CreateBase(parent
, id
, pos
, size
, style
, wxDefaultValidator
, name
) ) 
 608         parent
->AddChild(this); 
 611     x 
= pos
.x
, y 
= pos
.y
; 
 613         x 
= 0; // FIXME_MGL, something better, see GTK+ 
 615         y 
= 0; // FIXME_MGL, something better, see GTK+ 
 616     AdjustForParentClientOrigin(x
, y
, 0); 
 617     w 
= WidthDefault(size
.x
); 
 618     h 
= HeightDefault(size
.y
); 
 621     window_t 
*wnd_parent 
= parent 
? parent
->GetHandle() : NULL
; 
 623     if ( style 
& wxFULL_REPAINT_ON_RESIZE 
) 
 625         mgl_style 
|= MGL_WM_FULL_REPAINT_ON_RESIZE
; 
 627     if ( style 
& wxSTAY_ON_TOP 
) 
 629         mgl_style 
|= MGL_WM_ALWAYS_ON_TOP
; 
 631     if ( style 
& wxPOPUP_WINDOW 
) 
 633         mgl_style 
|= MGL_WM_ALWAYS_ON_TOP
; 
 634         // it is created hidden as other top level windows 
 639     window_t 
*wnd 
= MGL_wmCreateWindow(g_winMng
, wnd_parent
, x
, y
, w
, h
); 
 641     MGL_wmSetWindowFlags(wnd
, mgl_style
); 
 642     MGL_wmShowWindow(wnd
, m_isShown
); 
 649 void wxWindowMGL::SetMGLwindow_t(struct window_t 
*wnd
) 
 652         MGL_wmDestroyWindow(m_wnd
); 
 655     if ( !m_wnd 
) return; 
 657     m_isShown 
= (bool)m_wnd
->visible
; 
 659     MGL_wmSetWindowUserData(m_wnd
, (void*) this); 
 660     MGL_wmSetWindowPainter(m_wnd
, wxWindowPainter
); 
 661     MGL_wmPushWindowEventHandler(m_wnd
, wxWindowMouseHandler
, EVT_MOUSEEVT
, 0); 
 662     MGL_wmPushWindowEventHandler(m_wnd
, wxWindowKeybHandler
, EVT_KEYEVT
, 0); 
 665         MGL_wmSetWindowCursor(m_wnd
, *m_cursor
.GetMGLCursor()); 
 667         MGL_wmSetWindowCursor(m_wnd
, *wxSTANDARD_CURSOR
->GetMGLCursor()); 
 670 // --------------------------------------------------------------------------- 
 672 // --------------------------------------------------------------------------- 
 674 void wxWindowMGL::SetFocus() 
 676     if ( gs_focusedWindow 
== this ) return; 
 678     wxWindowMGL 
*oldFocusedWindow 
= gs_focusedWindow
; 
 680     if ( gs_focusedWindow 
) 
 682         gs_toBeFocusedWindow 
= (wxWindow
*)this; 
 683         gs_focusedWindow
->KillFocus(); 
 684         gs_toBeFocusedWindow 
= NULL
; 
 687     gs_focusedWindow 
= this; 
 689     MGL_wmCaptureEvents(GetHandle(), EVT_KEYEVT
, wxMGL_CAPTURE_KEYB
); 
 691     wxWindowMGL 
*active 
= wxGetTopLevelParent(this); 
 692     if ( !(m_windowStyle 
& wxPOPUP_WINDOW
) && active 
!= gs_activeFrame 
) 
 694         if ( gs_activeFrame 
) 
 696             wxActivateEvent 
event(wxEVT_ACTIVATE
, false, gs_activeFrame
->GetId()); 
 697             event
.SetEventObject(gs_activeFrame
); 
 698             gs_activeFrame
->GetEventHandler()->ProcessEvent(event
); 
 701         gs_activeFrame 
= active
; 
 702         wxActivateEvent 
event(wxEVT_ACTIVATE
, true, gs_activeFrame
->GetId()); 
 703         event
.SetEventObject(gs_activeFrame
); 
 704         gs_activeFrame
->GetEventHandler()->ProcessEvent(event
); 
 707     wxFocusEvent 
event(wxEVT_SET_FOCUS
, GetId()); 
 708     event
.SetEventObject(this); 
 709     event
.SetWindow((wxWindow
*)oldFocusedWindow
); 
 710     GetEventHandler()->ProcessEvent(event
); 
 713     // caret needs to be informed about focus change 
 714     wxCaret 
*caret 
= GetCaret(); 
 717 #endif // wxUSE_CARET 
 720 void wxWindowMGL::KillFocus() 
 722     if ( gs_focusedWindow 
!= this ) return; 
 723     gs_focusedWindow 
= NULL
; 
 725     if ( m_isBeingDeleted 
) return; 
 727     MGL_wmUncaptureEvents(GetHandle(), wxMGL_CAPTURE_KEYB
); 
 730     // caret needs to be informed about focus change 
 731     wxCaret 
*caret 
= GetCaret(); 
 733         caret
->OnKillFocus(); 
 734 #endif // wxUSE_CARET 
 736     wxFocusEvent 
event(wxEVT_KILL_FOCUS
, GetId()); 
 737     event
.SetEventObject(this); 
 738     event
.SetWindow(gs_toBeFocusedWindow
); 
 739     GetEventHandler()->ProcessEvent(event
); 
 742 // ---------------------------------------------------------------------------- 
 743 // this wxWindowBase function is implemented here (in platform-specific file) 
 744 // because it is static and so couldn't be made virtual 
 745 // ---------------------------------------------------------------------------- 
 746 wxWindow 
*wxWindowBase::DoFindFocus() 
 748     return (wxWindow
*)gs_focusedWindow
; 
 751 bool wxWindowMGL::Show(bool show
) 
 753     if ( !wxWindowBase::Show(show
) ) 
 756     MGL_wmShowWindow(m_wnd
, show
); 
 758     if (!show 
&& gs_activeFrame 
== this) 
 760         // activate next frame in Z-order: 
 763             wxWindowMGL 
*win 
= (wxWindowMGL
*)m_wnd
->prev
->userData
; 
 766         else if ( m_wnd
->next 
) 
 768             wxWindowMGL 
*win 
= (wxWindowMGL
*)m_wnd
->next
->userData
; 
 773             gs_activeFrame 
= NULL
; 
 780 // Raise the window to the top of the Z order 
 781 void wxWindowMGL::Raise() 
 783     MGL_wmRaiseWindow(m_wnd
); 
 786 // Lower the window to the bottom of the Z order 
 787 void wxWindowMGL::Lower() 
 789     MGL_wmLowerWindow(m_wnd
); 
 792 void wxWindowMGL::DoCaptureMouse() 
 794     if ( gs_mouseCapture 
) 
 795         MGL_wmUncaptureEvents(gs_mouseCapture
->m_wnd
, wxMGL_CAPTURE_MOUSE
); 
 797     gs_mouseCapture 
= this; 
 798     MGL_wmCaptureEvents(m_wnd
, EVT_MOUSEEVT
, wxMGL_CAPTURE_MOUSE
); 
 801 void wxWindowMGL::DoReleaseMouse() 
 803     wxASSERT_MSG( gs_mouseCapture 
== this, wxT("attempt to release mouse, but this window hasn't captured it") ); 
 805     MGL_wmUncaptureEvents(m_wnd
, wxMGL_CAPTURE_MOUSE
); 
 806     gs_mouseCapture 
= NULL
; 
 809 /* static */ wxWindow 
*wxWindowBase::GetCapture() 
 811     return (wxWindow
*)gs_mouseCapture
; 
 814 bool wxWindowMGL::SetCursor(const wxCursor
& cursor
) 
 816     if ( !wxWindowBase::SetCursor(cursor
) ) 
 823         MGL_wmSetWindowCursor(m_wnd
, *m_cursor
.GetMGLCursor()); 
 825         MGL_wmSetWindowCursor(m_wnd
, *wxSTANDARD_CURSOR
->GetMGLCursor()); 
 830 void wxWindowMGL::WarpPointer(int x
, int y
) 
 833     wxDisplaySize(&w
, &h
); 
 835     ClientToScreen(&x
, &y
); 
 845     EVT_setMousePos(x
, y
); 
 848 // Set this window to be the child of 'parent'. 
 849 bool wxWindowMGL::Reparent(wxWindowBase 
*parent
) 
 851     if ( !wxWindowBase::Reparent(parent
) ) 
 854     MGL_wmReparentWindow(m_wnd
, parent
->GetHandle()); 
 860 // --------------------------------------------------------------------------- 
 862 // --------------------------------------------------------------------------- 
 864 #if wxUSE_DRAG_AND_DROP 
 866 void wxWindowMGL::SetDropTarget(wxDropTarget 
*pDropTarget
) 
 868     if ( m_dropTarget 
!= 0 ) { 
 869         m_dropTarget
->Revoke(m_hWnd
); 
 873     m_dropTarget 
= pDropTarget
; 
 874     if ( m_dropTarget 
!= 0 ) 
 875         m_dropTarget
->Register(m_hWnd
); 
 878 #endif // wxUSE_DRAG_AND_DROP 
 880 // old style file-manager drag&drop support: we retain the old-style 
 881 // DragAcceptFiles in parallel with SetDropTarget. 
 882 void wxWindowMGL::DragAcceptFiles(bool WXUNUSED(accept
)) 
 885     HWND hWnd 
= GetHwnd(); 
 887         ::DragAcceptFiles(hWnd
, (BOOL
)accept
); 
 891 // --------------------------------------------------------------------------- 
 892 // moving and resizing 
 893 // --------------------------------------------------------------------------- 
 896 void wxWindowMGL::DoGetSize(int *x
, int *y
) const 
 898     wxASSERT_MSG( m_wnd
, wxT("invalid window") ); 
 900     if (x
) *x 
= m_wnd
->width
; 
 901     if (y
) *y 
= m_wnd
->height
; 
 904 void wxWindowMGL::DoGetPosition(int *x
, int *y
) const 
 906     wxASSERT_MSG( m_wnd
, wxT("invalid window") ); 
 909     AdjustForParentClientOrigin(pX
, pY
, 0); 
 911     if (x
) *x 
= m_wnd
->x 
- pX
; 
 912     if (y
) *y 
= m_wnd
->y 
- pY
; 
 915 void wxWindowMGL::DoScreenToClient(int *x
, int *y
) const 
 918     MGL_wmCoordGlobalToLocal(m_wnd
, 0, 0, &ax
, &ay
); 
 925 void wxWindowMGL::DoClientToScreen(int *x
, int *y
) const 
 928     MGL_wmCoordLocalToGlobal(m_wnd
, 0, 0, &ax
, &ay
); 
 935 // Get size *available for subwindows* i.e. excluding menu bar etc. 
 936 void wxWindowMGL::DoGetClientSize(int *x
, int *y
) const 
 941 void wxWindowMGL::DoMoveWindow(int x
, int y
, int width
, int height
) 
 943     wxRect 
rcClient(GetClientRect()); 
 945     MGL_wmSetWindowPosition(m_wnd
, x
, y
, width
, height
); 
 947     // When the origin or a window stays fixed but the height or width 
 948     // changes, invalidate the old and new non-client areas 
 949     if ( !HasFlag(wxFULL_REPAINT_ON_RESIZE
) && 
 950          m_wnd
->x 
== x 
&& m_wnd
->y 
== y 
&& 
 951          rcClient
.Intersect(GetClientRect()) != wxRect(0, 0, width
, height
) ) 
 953         wxRegion 
rgn(0, 0, width
, height
); 
 954         rgn
.Subtract(rcClient
); 
 956         // This should work I think, but doesn't seem to: 
 957         //MGL_wmInvalidateWindowRegion(m_wnd, rgn.GetMGLRegion().rgnPointer()); 
 959         // Use MGL_wmInvalidateWindowRect instead: 
 960         for (wxRegionIterator 
it(rgn
); it
; it
++) 
 965             rc
.right 
= rc
.left 
+ it
.GetW(); 
 966             rc
.bottom 
= rc
.top 
+ it
.GetH(); 
 967             MGL_wmInvalidateWindowRect(m_wnd
, &rc
); 
 972 // set the size of the window: if the dimensions are positive, just use them, 
 973 // but if any of them is equal to -1, it means that we must find the value for 
 974 // it ourselves (unless sizeFlags contains wxSIZE_ALLOW_MINUS_ONE flag, in 
 975 // which case -1 is a valid value for x and y) 
 977 // If sizeFlags contains wxSIZE_AUTO_WIDTH/HEIGHT flags (default), we calculate 
 978 // the width/height to best suit our contents, otherwise we reuse the current 
 980 void wxWindowMGL::DoSetSize(int x
, int y
, int width
, int height
, int sizeFlags
) 
 982     // get the current size and position... 
 983     int currentX
, currentY
; 
 984     GetPosition(¤tX
, ¤tY
); 
 985     int currentW
,currentH
; 
 986     GetSize(¤tW
, ¤tH
); 
 988     // ... and don't do anything (avoiding flicker) if it's already ok 
 989     if ( x 
== currentX 
&& y 
== currentY 
&& 
 990          width 
== currentW 
&& height 
== currentH 
) 
 995     if ( x 
== -1 && !(sizeFlags 
& wxSIZE_ALLOW_MINUS_ONE
) ) 
 997     if ( y 
== -1 && !(sizeFlags 
& wxSIZE_ALLOW_MINUS_ONE
) ) 
1000     AdjustForParentClientOrigin(x
, y
, sizeFlags
); 
1002     wxSize 
size(-1, -1); 
1005         if ( sizeFlags 
& wxSIZE_AUTO_WIDTH 
) 
1007             size 
= DoGetBestSize(); 
1012             // just take the current one 
1019         if ( sizeFlags 
& wxSIZE_AUTO_HEIGHT 
) 
1023                 size 
= DoGetBestSize(); 
1025             //else: already called DoGetBestSize() above 
1031             // just take the current one 
1036     int maxWidth 
= GetMaxWidth(), 
1037         minWidth 
= GetMinWidth(), 
1038         maxHeight 
= GetMaxHeight(), 
1039         minHeight 
= GetMinHeight(); 
1041     if ( minWidth 
!= -1 && width 
< minWidth 
) width 
= minWidth
; 
1042     if ( maxWidth 
!= -1 && width 
> maxWidth 
) width 
= maxWidth
; 
1043     if ( minHeight 
!= -1 && height 
< minHeight 
) height 
= minHeight
; 
1044     if ( maxHeight 
!= -1 && height 
> maxHeight 
) height 
= maxHeight
; 
1046     if ( m_wnd
->x 
!= x 
|| m_wnd
->y 
!= y 
|| 
1047          (int)m_wnd
->width 
!= width 
|| (int)m_wnd
->height 
!= height 
) 
1049         DoMoveWindow(x
, y
, width
, height
); 
1051         wxSize 
newSize(width
, height
); 
1052         wxSizeEvent 
event(newSize
, GetId()); 
1053         event
.SetEventObject(this); 
1054         GetEventHandler()->ProcessEvent(event
); 
1058 void wxWindowMGL::DoSetClientSize(int width
, int height
) 
1060     SetSize(width
, height
); 
1063 // --------------------------------------------------------------------------- 
1065 // --------------------------------------------------------------------------- 
1067 int wxWindowMGL::GetCharHeight() const 
1071     return dc
.GetCharHeight(); 
1074 int wxWindowMGL::GetCharWidth() const 
1078     return dc
.GetCharWidth(); 
1081 void wxWindowMGL::GetTextExtent(const wxString
& string
, 
1083                              int *descent
, int *externalLeading
, 
1084                              const wxFont 
*theFont
) const 
1089     dc
.GetTextExtent(string
, x
, y
, descent
, externalLeading
, (wxFont
*)theFont
); 
1093 // --------------------------------------------------------------------------- 
1095 // --------------------------------------------------------------------------- 
1097 void wxWindowMGL::Clear() 
1099     wxClientDC 
dc((wxWindow 
*)this); 
1100     wxBrush 
brush(GetBackgroundColour(), wxSOLID
); 
1101     dc
.SetBackground(brush
); 
1105 void wxWindowMGL::Refresh(bool eraseBack
, const wxRect 
*rect
) 
1107     if ( m_eraseBackground 
== -1 ) 
1108         m_eraseBackground 
= eraseBack
; 
1110         m_eraseBackground 
|= eraseBack
; 
1115         r
.left 
= rect
->GetLeft(), r
.right 
= rect
->GetRight(); 
1116         r
.top 
= rect
->GetTop(), r
.bottom 
= rect
->GetBottom(); 
1117         MGL_wmInvalidateWindowRect(GetHandle(), &r
); 
1120         MGL_wmInvalidateWindow(GetHandle()); 
1123 void wxWindowMGL::Update() 
1126         MGL_wmUpdateDC(g_winMng
); 
1129 void wxWindowMGL::Freeze() 
1132     m_refreshAfterThaw 
= false; 
1135 void wxWindowMGL::Thaw() 
1138     if ( m_refreshAfterThaw 
) 
1142 void wxWindowMGL::HandlePaint(MGLDevCtx 
*dc
) 
1146         // Don't paint anything if the window is frozen. 
1147         m_refreshAfterThaw 
= true; 
1152     // FIXME_MGL -- debugging stuff, to be removed! 
1153     static int debugPaintEvents 
= -1; 
1154     if ( debugPaintEvents 
== -1 ) 
1155         debugPaintEvents 
= wxGetEnv(wxT("WXMGL_DEBUG_PAINT_EVENTS"), NULL
); 
1156     if ( debugPaintEvents 
) 
1158         dc
->setColorRGB(255,0,255); 
1159         dc
->fillRect(-1000,-1000,2000,2000); 
1165     dc
->getClipRegion(clip
); 
1166     m_updateRegion 
= wxRegion(clip
); 
1170     // must hide caret temporarily, otherwise we'd get rendering artifacts 
1171     wxCaret 
*caret 
= GetCaret(); 
1174 #endif // wxUSE_CARET 
1176     if ( m_eraseBackground 
!= 0 ) 
1178         wxWindowDC 
dc((wxWindow
*)this); 
1179         wxEraseEvent 
eventEr(m_windowId
, &dc
); 
1180         eventEr
.SetEventObject(this); 
1181         GetEventHandler()->ProcessEvent(eventEr
); 
1183     m_eraseBackground 
= -1; 
1185     wxNcPaintEvent 
eventNc(GetId()); 
1186     eventNc
.SetEventObject(this); 
1187     GetEventHandler()->ProcessEvent(eventNc
); 
1189     wxPaintEvent 
eventPt(GetId()); 
1190     eventPt
.SetEventObject(this); 
1191     GetEventHandler()->ProcessEvent(eventPt
); 
1196 #endif // wxUSE_CARET 
1198     m_paintMGLDC 
= NULL
; 
1199     m_updateRegion
.Clear(); 
1203 // Find the wxWindow at the current mouse position, returning the mouse 
1205 wxWindow
* wxFindWindowAtPointer(wxPoint
& pt
) 
1207     return wxFindWindowAtPoint(pt 
= wxGetMousePosition()); 
1210 wxWindow
* wxFindWindowAtPoint(const wxPoint
& pt
) 
1212     window_t 
*wnd 
= MGL_wmGetWindowAtPosition(g_winMng
, pt
.x
, pt
.y
); 
1213     return (wxWindow
*)wnd
->userData
; 
1217 // --------------------------------------------------------------------------- 
1218 // idle events processing 
1219 // --------------------------------------------------------------------------- 
1221 void wxWindowMGL::OnInternalIdle() 
1223     if (wxUpdateUIEvent::CanUpdate(this)) 
1224         UpdateWindowUI(wxUPDATE_UI_FROMIDLE
);