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 license
9 /////////////////////////////////////////////////////////////////////////////
11 // ===========================================================================
13 // ===========================================================================
15 // ---------------------------------------------------------------------------
17 // ---------------------------------------------------------------------------
20 #pragma implementation "window.h"
23 // For compilers that support precompilation, includes "wx.h".
24 #include "wx/wxprec.h"
31 #include "wx/window.h"
32 #include "wx/msgdlg.h"
36 #include "wx/dcclient.h"
43 #if wxUSE_DRAG_AND_DROP
48 #include "wx/sysopt.h"
49 #include "wx/mgl/private.h"
51 #include "wx/dcscreen.h"
56 #include "wx/tooltip.h"
59 // ---------------------------------------------------------------------------
61 // ---------------------------------------------------------------------------
63 // MGL window manager and associated DC.
64 winmng_t
*g_winMng
= NULL
;
65 MGLDevCtx
*g_displayDC
= NULL
;
67 // the window that has keyboard focus:
68 static wxWindowMGL
*gs_focusedWindow
= NULL
;
69 // the window that is about to be focused after currently focused
71 static wxWindow
*gs_toBeFocusedWindow
= NULL
;
72 // the window that is currently under mouse cursor:
73 static wxWindowMGL
*gs_windowUnderMouse
= NULL
;
74 // the window that has mouse capture
75 static wxWindowMGL
*gs_mouseCapture
= NULL
;
76 // the frame that is currently active (i.e. its child has focus). It is
77 // used to generate wxActivateEvents
78 static wxWindowMGL
*gs_activeFrame
= NULL
;
80 // ---------------------------------------------------------------------------
82 // ---------------------------------------------------------------------------
84 // Custom identifiers used to distinguish between various event handlers
85 // and capture handlers passed to MGL_wm
88 wxMGL_CAPTURE_MOUSE
= 1,
89 wxMGL_CAPTURE_KEYB
= 2
93 // ---------------------------------------------------------------------------
95 // ---------------------------------------------------------------------------
97 // Returns toplevel grandparent of given window:
98 static wxWindowMGL
* wxGetTopLevelParent(wxWindowMGL
*win
)
100 wxWindowMGL
*p
= win
;
101 while (p
&& !p
->IsTopLevel())
106 // An easy way to capture screenshots:
107 static void wxCaptureScreenshot()
110 #define SCREENSHOT_FILENAME _T("sshot%03i.png")
112 #define SCREENSHOT_FILENAME _T("screenshot-%03i.png")
114 static int screenshot_num
= 0;
119 screenshot
.Printf(SCREENSHOT_FILENAME
, screenshot_num
++);
120 } while ( wxFileExists(screenshot
) && screenshot_num
< 1000 );
122 g_displayDC
->savePNGFromDC(screenshot
.mb_str(), 0, 0,
123 g_displayDC
->sizex(),
124 g_displayDC
->sizey());
126 wxMessageBox(_("Screenshot captured: ") + wxString(screenshot
));
129 // ---------------------------------------------------------------------------
131 // ---------------------------------------------------------------------------
133 static void MGLAPI
wxWindowPainter(window_t
*wnd
, MGLDC
*dc
)
135 wxWindowMGL
*w
= (wxWindow
*) wnd
->userData
;
137 if ( w
&& !(w
->GetWindowStyle() & wxTRANSPARENT_WINDOW
) )
140 w
->HandlePaint(&ctx
);
144 static ibool MGLAPI
wxWindowMouseHandler(window_t
*wnd
, event_t
*e
)
146 wxWindowMGL
*win
= (wxWindowMGL
*)MGL_wmGetWindowUserData(wnd
);
147 wxPoint
orig(win
->GetClientAreaOrigin());
150 MGL_wmCoordGlobalToLocal(win
->GetHandle(),
151 e
->where_x
, e
->where_y
, &where
.x
, &where
.y
);
153 for (wxWindowMGL
*w
= win
; w
; w
= w
->GetParent())
155 if ( !w
->IsEnabled() )
157 if ( w
->IsTopLevel() )
161 wxEventType type
= wxEVT_NULL
;
163 event
.SetEventObject(win
);
164 event
.SetTimestamp(e
->when
);
165 event
.m_x
= where
.x
- orig
.x
;
166 event
.m_y
= where
.y
- orig
.y
;
167 event
.m_shiftDown
= e
->modifiers
& EVT_SHIFTKEY
;
168 event
.m_controlDown
= e
->modifiers
& EVT_CTRLSTATE
;
169 event
.m_altDown
= e
->modifiers
& EVT_LEFTALT
;
170 event
.m_metaDown
= e
->modifiers
& EVT_RIGHTALT
;
171 event
.m_leftDown
= e
->modifiers
& EVT_LEFTBUT
;
172 event
.m_middleDown
= e
->modifiers
& EVT_MIDDLEBUT
;
173 event
.m_rightDown
= e
->modifiers
& EVT_RIGHTBUT
;
178 if ( e
->message
& EVT_LEFTBMASK
)
179 type
= (e
->message
& EVT_DBLCLICK
) ?
180 wxEVT_LEFT_DCLICK
: wxEVT_LEFT_DOWN
;
181 else if ( e
->message
& EVT_MIDDLEBMASK
)
182 type
= (e
->message
& EVT_DBLCLICK
) ?
183 wxEVT_MIDDLE_DCLICK
: wxEVT_MIDDLE_DOWN
;
184 else if ( e
->message
& EVT_RIGHTBMASK
)
185 type
= (e
->message
& EVT_DBLCLICK
) ?
186 wxEVT_RIGHT_DCLICK
: wxEVT_RIGHT_DOWN
;
188 if ( win
->AcceptsFocus() && wxWindow::FindFocus() != win
)
194 if ( e
->message
& EVT_LEFTBMASK
)
195 type
= wxEVT_LEFT_UP
;
196 else if ( e
->message
& EVT_MIDDLEBMASK
)
197 type
= wxEVT_MIDDLE_UP
;
198 else if ( e
->message
& EVT_RIGHTBMASK
)
199 type
= wxEVT_RIGHT_UP
;
203 if ( !gs_mouseCapture
)
205 if ( win
!= gs_windowUnderMouse
)
207 if ( gs_windowUnderMouse
)
209 wxMouseEvent
event2(event
);
210 MGL_wmCoordGlobalToLocal(gs_windowUnderMouse
->GetHandle(),
211 e
->where_x
, e
->where_y
,
212 &event2
.m_x
, &event2
.m_y
);
214 wxPoint
orig(gs_windowUnderMouse
->GetClientAreaOrigin());
215 event2
.m_x
-= orig
.x
;
216 event2
.m_y
-= orig
.y
;
218 event2
.SetEventObject(gs_windowUnderMouse
);
219 event2
.SetEventType(wxEVT_LEAVE_WINDOW
);
220 gs_windowUnderMouse
->GetEventHandler()->ProcessEvent(event2
);
223 wxMouseEvent
event3(event
);
224 event3
.SetEventType(wxEVT_ENTER_WINDOW
);
225 win
->GetEventHandler()->ProcessEvent(event3
);
227 gs_windowUnderMouse
= win
;
230 else // gs_mouseCapture
232 bool inside
= (where
.x
>= 0 &&
234 where
.x
< win
->GetSize().x
&&
235 where
.y
< win
->GetSize().y
);
236 if ( (inside
&& gs_windowUnderMouse
!= win
) ||
237 (!inside
&& gs_windowUnderMouse
== win
) )
239 wxMouseEvent
evt(inside
?
240 wxEVT_ENTER_WINDOW
: wxEVT_LEAVE_WINDOW
);
241 evt
.SetEventObject(win
);
242 win
->GetEventHandler()->ProcessEvent(evt
);
243 gs_windowUnderMouse
= inside
? win
: NULL
;
254 if ( type
== wxEVT_NULL
)
260 event
.SetEventType(type
);
261 return win
->GetEventHandler()->ProcessEvent(event
);
265 static long wxScanToKeyCode(event_t
*event
, bool translate
)
267 // VS: make it __WXDEBUG__-only, since we have lots of wxLogTrace calls
268 // here and the arguments would be stored in non-debug executable even
269 // though wxLogTrace would be no-op...
271 #define KEY(mgl_key,wx_key) \
273 wxLogTrace(_T("keyevents"), \
274 _T("key " #mgl_key ", mapped to " #wx_key)); \
278 #define KEY(mgl_key,wx_key) \
279 case mgl_key: key = wx_key; break;
286 switch ( EVT_scanCode(event
->message
) )
288 KEY (KB_padMinus
, WXK_NUMPAD_SUBTRACT
)
289 KEY (KB_padPlus
, WXK_NUMPAD_ADD
)
290 KEY (KB_padTimes
, WXK_NUMPAD_MULTIPLY
)
291 KEY (KB_padDivide
, WXK_NUMPAD_DIVIDE
)
292 KEY (KB_padCenter
, WXK_NUMPAD_SEPARATOR
) // ?
293 KEY (KB_padLeft
, WXK_NUMPAD_LEFT
)
294 KEY (KB_padRight
, WXK_NUMPAD_RIGHT
)
295 KEY (KB_padUp
, WXK_NUMPAD_UP
)
296 KEY (KB_padDown
, WXK_NUMPAD_DOWN
)
297 KEY (KB_padInsert
, WXK_NUMPAD_INSERT
)
298 KEY (KB_padDelete
, WXK_NUMPAD_DELETE
)
299 KEY (KB_padHome
, WXK_NUMPAD_HOME
)
300 KEY (KB_padEnd
, WXK_NUMPAD_END
)
301 KEY (KB_padPageUp
, WXK_NUMPAD_PAGEUP
)
302 //KEY (KB_padPageUp, WXK_NUMPAD_PRIOR)
303 KEY (KB_padPageDown
, WXK_NUMPAD_PAGEDOWN
)
304 //KEY (KB_padPageDown, WXK_NUMPAD_NEXT)
315 KEY (KB_minus
, WXK_SUBTRACT
)
316 KEY (KB_equals
, WXK_ADD
)
317 KEY (KB_backSlash
, '\\')
328 KEY (KB_leftSquareBrace
,'[')
329 KEY (KB_rightSquareBrace
,']')
339 KEY (KB_semicolon
, ';')
340 KEY (KB_apostrophe
, '\'')
350 KEY (KB_divide
, WXK_DIVIDE
)
351 KEY (KB_space
, WXK_SPACE
)
360 switch ( EVT_scanCode(event
->message
) )
362 KEY (KB_padEnter
, WXK_NUMPAD_ENTER
)
372 KEY (KB_F10
, WXK_F10
)
373 KEY (KB_F11
, WXK_F11
)
374 KEY (KB_F12
, WXK_F12
)
375 KEY (KB_left
, WXK_LEFT
)
376 KEY (KB_right
, WXK_RIGHT
)
378 KEY (KB_down
, WXK_DOWN
)
379 KEY (KB_insert
, WXK_INSERT
)
380 KEY (KB_delete
, WXK_DELETE
)
381 KEY (KB_home
, WXK_HOME
)
382 KEY (KB_end
, WXK_END
)
383 KEY (KB_pageUp
, WXK_PAGEUP
)
384 KEY (KB_pageDown
, WXK_PAGEDOWN
)
385 KEY (KB_capsLock
, WXK_CAPITAL
)
386 KEY (KB_numLock
, WXK_NUMLOCK
)
387 KEY (KB_scrollLock
, WXK_SCROLL
)
388 KEY (KB_leftShift
, WXK_SHIFT
)
389 KEY (KB_rightShift
, WXK_SHIFT
)
390 KEY (KB_leftCtrl
, WXK_CONTROL
)
391 KEY (KB_rightCtrl
, WXK_CONTROL
)
392 KEY (KB_leftAlt
, WXK_ALT
)
393 KEY (KB_rightAlt
, WXK_ALT
)
394 KEY (KB_leftWindows
, WXK_START
)
395 KEY (KB_rightWindows
, WXK_START
)
396 KEY (KB_menu
, WXK_MENU
)
397 KEY (KB_sysReq
, WXK_SNAPSHOT
)
398 KEY (KB_esc
, WXK_ESCAPE
)
399 KEY (KB_backspace
, WXK_BACK
)
400 KEY (KB_tab
, WXK_TAB
)
401 KEY (KB_enter
, WXK_RETURN
)
404 key
= EVT_asciiCode(event
->message
);
414 static bool wxHandleSpecialKeys(wxKeyEvent
& event
)
416 // Add an easy way to capture screenshots:
417 if ( event
.m_keyCode
== WXK_SNAPSHOT
418 #ifdef __WXDEBUG__ // FIXME_MGL - remove when KB_sysReq works in MGL!
419 || (event
.m_keyCode
== WXK_F1
&&
420 event
.m_shiftDown
&& event
.m_controlDown
)
424 wxCaptureScreenshot();
428 if ( event
.m_keyCode
== WXK_F4
&& event
.m_altDown
&&
429 gs_activeFrame
!= NULL
)
431 gs_activeFrame
->Close();
438 static ibool MGLAPI
wxWindowKeybHandler(window_t
*wnd
, event_t
*e
)
440 wxWindowMGL
*win
= (wxWindowMGL
*)MGL_wmGetWindowUserData(wnd
);
442 if ( !win
->IsEnabled() ) return FALSE
;
445 MGL_wmCoordGlobalToLocal(win
->GetHandle(),
446 e
->where_x
, e
->where_y
, &where
.x
, &where
.y
);
449 event
.SetEventObject(win
);
450 event
.SetTimestamp(e
->when
);
451 event
.m_keyCode
= wxScanToKeyCode(e
, TRUE
);
452 event
.m_scanCode
= 0; // not used by wx at all
455 event
.m_shiftDown
= e
->modifiers
& EVT_SHIFTKEY
;
456 event
.m_controlDown
= e
->modifiers
& EVT_CTRLSTATE
;
457 event
.m_altDown
= e
->modifiers
& EVT_LEFTALT
;
458 event
.m_metaDown
= e
->modifiers
& EVT_RIGHTALT
;
460 if ( e
->what
== EVT_KEYUP
)
462 event
.SetEventType(wxEVT_KEY_UP
);
463 return win
->GetEventHandler()->ProcessEvent(event
);
470 event
.SetEventType(wxEVT_KEY_DOWN
);
473 ret
= win
->GetEventHandler()->ProcessEvent(event
);
475 // wxMSW doesn't send char events with Alt pressed
476 // Only send wxEVT_CHAR event if not processed yet. Thus, ALT-x
477 // will only be sent if it is not in an accelerator table:
478 event2
.m_keyCode
= wxScanToKeyCode(e
, FALSE
);
479 if ( !ret
&& event2
.m_keyCode
!= 0 )
481 event2
.SetEventType(wxEVT_CHAR
);
482 ret
= win
->GetEventHandler()->ProcessEvent(event2
);
485 // Synthetize navigation key event, but do it only if the TAB key
486 // wasn't handled yet:
487 if ( !ret
&& event
.m_keyCode
== WXK_TAB
&&
488 win
->GetParent() && win
->GetParent()->HasFlag(wxTAB_TRAVERSAL
) )
490 wxNavigationKeyEvent navEvent
;
491 navEvent
.SetEventObject(win
->GetParent());
492 // Shift-TAB goes in reverse direction:
493 navEvent
.SetDirection(!event
.m_shiftDown
);
494 // Ctrl-TAB changes the (parent) window, i.e. switch notebook page:
495 navEvent
.SetWindowChange(event
.m_controlDown
);
496 navEvent
.SetCurrentFocus(wxStaticCast(win
, wxWindow
));
497 ret
= win
->GetParent()->GetEventHandler()->ProcessEvent(navEvent
);
500 // Finally, process special meaning keys that are usually
501 // a responsibility of OS or window manager:
503 ret
= wxHandleSpecialKeys(event
);
509 // ---------------------------------------------------------------------------
511 // ---------------------------------------------------------------------------
513 // in wxUniv this class is abstract because it doesn't have DoPopupMenu()
514 IMPLEMENT_ABSTRACT_CLASS(wxWindowMGL
, wxWindowBase
)
516 BEGIN_EVENT_TABLE(wxWindowMGL
, wxWindowBase
)
517 EVT_IDLE(wxWindowMGL::OnIdle
)
520 // ===========================================================================
522 // ===========================================================================
524 // ----------------------------------------------------------------------------
525 // constructors and such
526 // ----------------------------------------------------------------------------
528 extern wxDisplayModeInfo
wxGetDefaultDisplayMode();
530 void wxWindowMGL::Init()
532 // First of all, make sure window manager is up and running. If it is
533 // not the case, initialize it in default display mode
536 if ( !wxTheApp
->SetDisplayMode(wxGetDefaultDisplayMode()) )
537 wxFatalError(_("Cannot initialize display."));
546 m_isBeingDeleted
= FALSE
;
550 m_eraseBackground
= -1;
554 wxWindowMGL::~wxWindowMGL()
556 m_isBeingDeleted
= TRUE
;
558 if ( gs_mouseCapture
== this )
561 if (gs_activeFrame
== this)
563 gs_activeFrame
= NULL
;
564 // activate next frame in Z-order:
567 wxWindowMGL
*win
= (wxWindowMGL
*)m_wnd
->prev
->userData
;
572 if ( gs_focusedWindow
== this )
575 if ( gs_windowUnderMouse
== this )
576 gs_windowUnderMouse
= NULL
;
578 // VS: destroy children first and _then_ detach *this from its parent.
579 // If we'd do it the other way around, children wouldn't be able
580 // find their parent frame (see above).
584 m_parent
->RemoveChild(this);
587 MGL_wmDestroyWindow(m_wnd
);
590 // real construction (Init() must have been called before!)
591 bool wxWindowMGL::Create(wxWindow
*parent
,
596 const wxString
& name
)
598 if ( !CreateBase(parent
, id
, pos
, size
, style
, wxDefaultValidator
, name
) )
602 parent
->AddChild(this);
605 x
= pos
.x
, y
= pos
.y
;
607 x
= 0; // FIXME_MGL, something better, see GTK+
609 y
= 0; // FIXME_MGL, something better, see GTK+
610 AdjustForParentClientOrigin(x
, y
, 0);
611 w
= WidthDefault(size
.x
);
612 h
= HeightDefault(size
.y
);
615 window_t
*wnd_parent
= parent
? parent
->GetHandle() : NULL
;
617 if ( !(style
& wxNO_FULL_REPAINT_ON_RESIZE
) )
619 mgl_style
|= MGL_WM_FULL_REPAINT_ON_RESIZE
;
621 if ( style
& wxSTAY_ON_TOP
)
623 mgl_style
|= MGL_WM_ALWAYS_ON_TOP
;
625 if ( style
& wxPOPUP_WINDOW
)
627 mgl_style
|= MGL_WM_ALWAYS_ON_TOP
;
628 // it is created hidden as other top level windows
633 window_t
*wnd
= MGL_wmCreateWindow(g_winMng
, wnd_parent
, x
, y
, w
, h
);
635 MGL_wmSetWindowFlags(wnd
, mgl_style
);
636 MGL_wmShowWindow(wnd
, m_isShown
);
643 void wxWindowMGL::SetMGLwindow_t(struct window_t
*wnd
)
646 MGL_wmDestroyWindow(m_wnd
);
649 if ( !m_wnd
) return;
651 m_isShown
= m_wnd
->visible
;
653 MGL_wmSetWindowUserData(m_wnd
, (void*) this);
654 MGL_wmSetWindowPainter(m_wnd
, wxWindowPainter
);
655 MGL_wmPushWindowEventHandler(m_wnd
, wxWindowMouseHandler
, EVT_MOUSEEVT
, 0);
656 MGL_wmPushWindowEventHandler(m_wnd
, wxWindowKeybHandler
, EVT_KEYEVT
, 0);
659 MGL_wmSetWindowCursor(m_wnd
, *m_cursor
.GetMGLCursor());
661 MGL_wmSetWindowCursor(m_wnd
, *wxSTANDARD_CURSOR
->GetMGLCursor());
664 // ---------------------------------------------------------------------------
666 // ---------------------------------------------------------------------------
668 void wxWindowMGL::SetFocus()
670 if ( gs_focusedWindow
== this ) return;
672 wxWindowMGL
*oldFocusedWindow
= gs_focusedWindow
;
674 if ( gs_focusedWindow
)
676 gs_toBeFocusedWindow
= (wxWindow
*)this;
677 gs_focusedWindow
->KillFocus();
678 gs_toBeFocusedWindow
= NULL
;
681 gs_focusedWindow
= this;
683 MGL_wmCaptureEvents(GetHandle(), EVT_KEYEVT
, wxMGL_CAPTURE_KEYB
);
685 wxWindowMGL
*active
= wxGetTopLevelParent(this);
686 if ( !(m_windowStyle
& wxPOPUP_WINDOW
) && active
!= gs_activeFrame
)
688 if ( gs_activeFrame
)
690 wxActivateEvent
event(wxEVT_ACTIVATE
, FALSE
, gs_activeFrame
->GetId());
691 event
.SetEventObject(gs_activeFrame
);
692 gs_activeFrame
->GetEventHandler()->ProcessEvent(event
);
695 gs_activeFrame
= active
;
696 wxActivateEvent
event(wxEVT_ACTIVATE
, TRUE
, gs_activeFrame
->GetId());
697 event
.SetEventObject(gs_activeFrame
);
698 gs_activeFrame
->GetEventHandler()->ProcessEvent(event
);
701 wxFocusEvent
event(wxEVT_SET_FOCUS
, GetId());
702 event
.SetEventObject(this);
703 event
.SetWindow((wxWindow
*)oldFocusedWindow
);
704 GetEventHandler()->ProcessEvent(event
);
707 // caret needs to be informed about focus change
708 wxCaret
*caret
= GetCaret();
711 #endif // wxUSE_CARET
714 void wxWindowMGL::KillFocus()
716 if ( gs_focusedWindow
!= this ) return;
717 gs_focusedWindow
= NULL
;
719 if ( m_isBeingDeleted
) return;
721 MGL_wmUncaptureEvents(GetHandle(), wxMGL_CAPTURE_KEYB
);
724 // caret needs to be informed about focus change
725 wxCaret
*caret
= GetCaret();
727 caret
->OnKillFocus();
728 #endif // wxUSE_CARET
730 wxFocusEvent
event(wxEVT_KILL_FOCUS
, GetId());
731 event
.SetEventObject(this);
732 event
.SetWindow(gs_toBeFocusedWindow
);
733 GetEventHandler()->ProcessEvent(event
);
736 // ----------------------------------------------------------------------------
737 // this wxWindowBase function is implemented here (in platform-specific file)
738 // because it is static and so couldn't be made virtual
739 // ----------------------------------------------------------------------------
740 wxWindow
*wxWindowBase::FindFocus()
742 return (wxWindow
*)gs_focusedWindow
;
745 bool wxWindowMGL::Show(bool show
)
747 if ( !wxWindowBase::Show(show
) )
750 MGL_wmShowWindow(m_wnd
, show
);
752 if (!show
&& gs_activeFrame
== this)
754 // activate next frame in Z-order:
757 wxWindowMGL
*win
= (wxWindowMGL
*)m_wnd
->prev
->userData
;
765 // Raise the window to the top of the Z order
766 void wxWindowMGL::Raise()
768 MGL_wmRaiseWindow(m_wnd
);
771 // Lower the window to the bottom of the Z order
772 void wxWindowMGL::Lower()
774 MGL_wmLowerWindow(m_wnd
);
777 void wxWindowMGL::DoCaptureMouse()
779 if ( gs_mouseCapture
)
780 MGL_wmUncaptureEvents(gs_mouseCapture
->m_wnd
, wxMGL_CAPTURE_MOUSE
);
782 gs_mouseCapture
= this;
783 MGL_wmCaptureEvents(m_wnd
, EVT_MOUSEEVT
, wxMGL_CAPTURE_MOUSE
);
786 void wxWindowMGL::DoReleaseMouse()
788 wxASSERT_MSG( gs_mouseCapture
== this, wxT("attempt to release mouse, but this window hasn't captured it") )
790 MGL_wmUncaptureEvents(m_wnd
, wxMGL_CAPTURE_MOUSE
);
791 gs_mouseCapture
= NULL
;
794 /* static */ wxWindow
*wxWindowBase::GetCapture()
796 return (wxWindow
*)gs_mouseCapture
;
799 bool wxWindowMGL::SetCursor(const wxCursor
& cursor
)
801 if ( !wxWindowBase::SetCursor(cursor
) )
808 MGL_wmSetWindowCursor(m_wnd
, *m_cursor
.GetMGLCursor());
810 MGL_wmSetWindowCursor(m_wnd
, *wxSTANDARD_CURSOR
->GetMGLCursor());
815 void wxWindowMGL::WarpPointer(int x
, int y
)
817 ClientToScreen(&x
, &y
);
818 EVT_setMousePos(x
, y
);
821 #if WXWIN_COMPATIBILITY
822 // If nothing defined for this, try the parent.
823 // E.g. we may be a button loaded from a resource, with no callback function
825 void wxWindowMGL::OnCommand(wxWindow
& win
, wxCommandEvent
& event
)
827 if ( GetEventHandler()->ProcessEvent(event
) )
830 m_parent
->GetEventHandler()->OnCommand(win
, event
);
832 #endif // WXWIN_COMPATIBILITY_2
834 #if WXWIN_COMPATIBILITY
835 wxObject
* wxWindowMGL::GetChild(int number
) const
837 // Return a pointer to the Nth object in the Panel
838 wxNode
*node
= GetChildren().First();
844 wxObject
*obj
= (wxObject
*)node
->Data();
850 #endif // WXWIN_COMPATIBILITY
852 // Set this window to be the child of 'parent'.
853 bool wxWindowMGL::Reparent(wxWindowBase
*parent
)
855 if ( !wxWindowBase::Reparent(parent
) )
858 MGL_wmReparentWindow(m_wnd
, parent
->GetHandle());
864 // ---------------------------------------------------------------------------
866 // ---------------------------------------------------------------------------
868 #if wxUSE_DRAG_AND_DROP
870 void wxWindowMGL::SetDropTarget(wxDropTarget
*pDropTarget
)
872 if ( m_dropTarget
!= 0 ) {
873 m_dropTarget
->Revoke(m_hWnd
);
877 m_dropTarget
= pDropTarget
;
878 if ( m_dropTarget
!= 0 )
879 m_dropTarget
->Register(m_hWnd
);
882 #endif // wxUSE_DRAG_AND_DROP
884 // old style file-manager drag&drop support: we retain the old-style
885 // DragAcceptFiles in parallel with SetDropTarget.
886 void wxWindowMGL::DragAcceptFiles(bool accept
)
889 HWND hWnd
= GetHwnd();
891 ::DragAcceptFiles(hWnd
, (BOOL
)accept
);
895 // ---------------------------------------------------------------------------
896 // moving and resizing
897 // ---------------------------------------------------------------------------
900 void wxWindowMGL::DoGetSize(int *x
, int *y
) const
902 wxASSERT_MSG( m_wnd
, wxT("invalid window") )
904 if (x
) *x
= m_wnd
->width
;
905 if (y
) *y
= m_wnd
->height
;
908 void wxWindowMGL::DoGetPosition(int *x
, int *y
) const
910 wxASSERT_MSG( m_wnd
, wxT("invalid window") )
912 if (x
) *x
= m_wnd
->x
;
913 if (y
) *y
= m_wnd
->y
;
916 void wxWindowMGL::DoScreenToClient(int *x
, int *y
) const
919 MGL_wmCoordGlobalToLocal(m_wnd
, 0, 0, &ax
, &ay
);
926 void wxWindowMGL::DoClientToScreen(int *x
, int *y
) const
929 MGL_wmCoordLocalToGlobal(m_wnd
, 0, 0, &ax
, &ay
);
936 // Get size *available for subwindows* i.e. excluding menu bar etc.
937 void wxWindowMGL::DoGetClientSize(int *x
, int *y
) const
942 void wxWindowMGL::DoMoveWindow(int x
, int y
, int width
, int height
)
944 MGL_wmSetWindowPosition(GetHandle(), x
, y
, width
, height
);
947 // set the size of the window: if the dimensions are positive, just use them,
948 // but if any of them is equal to -1, it means that we must find the value for
949 // it ourselves (unless sizeFlags contains wxSIZE_ALLOW_MINUS_ONE flag, in
950 // which case -1 is a valid value for x and y)
952 // If sizeFlags contains wxSIZE_AUTO_WIDTH/HEIGHT flags (default), we calculate
953 // the width/height to best suit our contents, otherwise we reuse the current
955 void wxWindowMGL::DoSetSize(int x
, int y
, int width
, int height
, int sizeFlags
)
957 // get the current size and position...
958 int currentX
, currentY
;
959 GetPosition(¤tX
, ¤tY
);
960 int currentW
,currentH
;
961 GetSize(¤tW
, ¤tH
);
963 // ... and don't do anything (avoiding flicker) if it's already ok
964 if ( x
== currentX
&& y
== currentY
&&
965 width
== currentW
&& height
== currentH
)
970 if ( x
== -1 && !(sizeFlags
& wxSIZE_ALLOW_MINUS_ONE
) )
972 if ( y
== -1 && !(sizeFlags
& wxSIZE_ALLOW_MINUS_ONE
) )
975 AdjustForParentClientOrigin(x
, y
, sizeFlags
);
980 if ( sizeFlags
& wxSIZE_AUTO_WIDTH
)
982 size
= DoGetBestSize();
987 // just take the current one
994 if ( sizeFlags
& wxSIZE_AUTO_HEIGHT
)
998 size
= DoGetBestSize();
1000 //else: already called DoGetBestSize() above
1006 // just take the current one
1011 int maxWidth
= GetMaxWidth(),
1012 minWidth
= GetMinWidth(),
1013 maxHeight
= GetMaxHeight(),
1014 minHeight
= GetMinHeight();
1016 if ( minWidth
!= -1 && width
< minWidth
) width
= minWidth
;
1017 if ( maxWidth
!= -1 && width
> maxWidth
) width
= maxWidth
;
1018 if ( minHeight
!= -1 && height
< minHeight
) height
= minHeight
;
1019 if ( maxHeight
!= -1 && height
> maxHeight
) height
= maxHeight
;
1021 if ( m_wnd
->x
!= x
|| m_wnd
->y
!= y
||
1022 (int)m_wnd
->width
!= width
|| (int)m_wnd
->height
!= height
)
1024 DoMoveWindow(x
, y
, width
, height
);
1026 wxSizeEvent
event(wxSize(width
, height
), GetId());
1027 event
.SetEventObject(this);
1028 GetEventHandler()->ProcessEvent(event
);
1032 void wxWindowMGL::DoSetClientSize(int width
, int height
)
1034 SetSize(width
, height
);
1037 // ---------------------------------------------------------------------------
1039 // ---------------------------------------------------------------------------
1041 int wxWindowMGL::GetCharHeight() const
1045 return dc
.GetCharHeight();
1048 int wxWindowMGL::GetCharWidth() const
1052 return dc
.GetCharWidth();
1055 void wxWindowMGL::GetTextExtent(const wxString
& string
,
1057 int *descent
, int *externalLeading
,
1058 const wxFont
*theFont
) const
1063 dc
.GetTextExtent(string
, x
, y
, descent
, externalLeading
, (wxFont
*)theFont
);
1066 #if wxUSE_CARET && WXWIN_COMPATIBILITY
1067 // ---------------------------------------------------------------------------
1068 // Caret manipulation
1069 // ---------------------------------------------------------------------------
1071 void wxWindowMGL::CreateCaret(int w
, int h
)
1073 SetCaret(new wxCaret(this, w
, h
));
1076 void wxWindowMGL::CreateCaret(const wxBitmap
*WXUNUSED(bitmap
))
1078 wxFAIL_MSG("not implemented");
1081 void wxWindowMGL::ShowCaret(bool show
)
1083 wxCHECK_RET( m_caret
, "no caret to show" );
1085 m_caret
->Show(show
);
1088 void wxWindowMGL::DestroyCaret()
1093 void wxWindowMGL::SetCaretPos(int x
, int y
)
1095 wxCHECK_RET( m_caret
, "no caret to move" );
1097 m_caret
->Move(x
, y
);
1100 void wxWindowMGL::GetCaretPos(int *x
, int *y
) const
1102 wxCHECK_RET( m_caret
, "no caret to get position of" );
1104 m_caret
->GetPosition(x
, y
);
1106 #endif // wxUSE_CARET
1109 // ---------------------------------------------------------------------------
1111 // ---------------------------------------------------------------------------
1113 void wxWindowMGL::Clear()
1115 wxClientDC
dc((wxWindow
*)this);
1116 wxBrush
brush(GetBackgroundColour(), wxSOLID
);
1117 dc
.SetBackground(brush
);
1121 #include "wx/menu.h"
1122 void wxWindowMGL::Refresh(bool eraseBack
, const wxRect
*rect
)
1124 if ( m_eraseBackground
== -1 )
1125 m_eraseBackground
= eraseBack
;
1127 m_eraseBackground
|= eraseBack
;
1132 r
.left
= rect
->GetLeft(), r
.right
= rect
->GetRight();
1133 r
.top
= rect
->GetTop(), r
.bottom
= rect
->GetBottom();
1134 MGL_wmInvalidateWindowRect(GetHandle(), &r
);
1137 MGL_wmInvalidateWindow(GetHandle());
1140 void wxWindowMGL::Update()
1143 MGL_wmUpdateDC(g_winMng
);
1146 void wxWindowMGL::Freeze()
1149 m_refreshAfterThaw
= FALSE
;
1152 void wxWindowMGL::Thaw()
1155 if ( m_refreshAfterThaw
)
1159 void wxWindowMGL::HandlePaint(MGLDevCtx
*dc
)
1163 // Don't paint anything if the window is frozen.
1164 m_refreshAfterThaw
= TRUE
;
1169 // FIXME_MGL -- debugging stuff, to be removed!
1170 static int debugPaintEvents
= -1;
1171 if ( debugPaintEvents
== -1 )
1172 debugPaintEvents
= wxGetEnv(wxT("WXMGL_DEBUG_PAINT_EVENTS"), NULL
);
1173 if ( debugPaintEvents
)
1175 dc
->setColorRGB(255,0,255);
1176 dc
->fillRect(-1000,-1000,2000,2000);
1182 dc
->getClipRegion(clip
);
1183 m_updateRegion
= wxRegion(clip
);
1187 // must hide caret temporarily, otherwise we'd get rendering artifacts
1188 wxCaret
*caret
= GetCaret();
1191 #endif // wxUSE_CARET
1193 if ( m_eraseBackground
!= 0 )
1195 wxWindowDC
dc((wxWindow
*)this);
1196 wxEraseEvent
eventEr(m_windowId
, &dc
);
1197 eventEr
.SetEventObject(this);
1198 GetEventHandler()->ProcessEvent(eventEr
);
1200 m_eraseBackground
= -1;
1202 wxNcPaintEvent
eventNc(GetId());
1203 eventNc
.SetEventObject(this);
1204 GetEventHandler()->ProcessEvent(eventNc
);
1206 wxPaintEvent
eventPt(GetId());
1207 eventPt
.SetEventObject(this);
1208 GetEventHandler()->ProcessEvent(eventPt
);
1213 #endif // wxUSE_CARET
1215 m_paintMGLDC
= NULL
;
1216 m_updateRegion
.Clear();
1220 // Find the wxWindow at the current mouse position, returning the mouse
1222 wxWindow
* wxFindWindowAtPointer(wxPoint
& pt
)
1224 return wxFindWindowAtPoint(pt
= wxGetMousePosition());
1227 wxWindow
* wxFindWindowAtPoint(const wxPoint
& pt
)
1229 window_t
*wnd
= MGL_wmGetWindowAtPosition(g_winMng
, pt
.x
, pt
.y
);
1230 return (wxWindow
*)wnd
->userData
;
1234 // ---------------------------------------------------------------------------
1235 // idle events processing
1236 // ---------------------------------------------------------------------------
1238 void wxWindowMGL::OnIdle(wxIdleEvent
& WXUNUSED(event
))