]> git.saurik.com Git - wxWidgets.git/blame - src/univ/topluniv.cpp
added wxWindow::IsFrozen() (only existed in wxMSW and wxDFB before)
[wxWidgets.git] / src / univ / topluniv.cpp
CommitLineData
0f1bf77d 1/////////////////////////////////////////////////////////////////////////////
1c067fe3 2// Name: src/univ/topluniv.cpp
0f1bf77d
VS
3// Author: Vaclav Slavik
4// Id: $Id$
52750c2e 5// Copyright: (c) 2001-2002 SciTech Software, Inc. (www.scitechsoft.com)
65571936 6// Licence: wxWindows licence
0f1bf77d
VS
7/////////////////////////////////////////////////////////////////////////////
8
9// ============================================================================
10// declarations
11// ============================================================================
12
13// ----------------------------------------------------------------------------
14// headers
15// ----------------------------------------------------------------------------
16
0f1bf77d
VS
17// For compilers that support precompilation, includes "wx.h".
18#include "wx/wxprec.h"
19
20#ifdef __BORLANDC__
1832043f 21 #pragma hdrstop
0f1bf77d
VS
22#endif
23
1832043f
WS
24#include "wx/toplevel.h"
25
f8e3449c
VS
26#ifndef WX_PRECOMP
27 #include "wx/dcclient.h"
28 #include "wx/settings.h"
0bca0373 29 #include "wx/bitmap.h"
155ecd4c 30 #include "wx/image.h"
dad5ae6d 31 #include "wx/frame.h"
f8e3449c
VS
32#endif
33
24a23c35 34#include "wx/univ/renderer.h"
813edf09 35#include "wx/cshelp.h"
621b405f 36#include "wx/evtloop.h"
0f1bf77d
VS
37
38
39// ----------------------------------------------------------------------------
40// event tables
41// ----------------------------------------------------------------------------
42
24a23c35 43BEGIN_EVENT_TABLE(wxTopLevelWindow, wxTopLevelWindowNative)
ea1b0d6c 44 WX_EVENT_TABLE_INPUT_CONSUMER(wxTopLevelWindow)
24a23c35 45 EVT_NC_PAINT(wxTopLevelWindow::OnNcPaint)
71cb2ca1 46 EVT_MENU_RANGE(wxID_CLOSE_FRAME, wxID_RESTORE_FRAME, wxTopLevelWindow::OnSystemMenu)
24a23c35
VS
47END_EVENT_TABLE()
48
ea1b0d6c
VS
49WX_FORWARD_TO_INPUT_CONSUMER(wxTopLevelWindow)
50
0f1bf77d
VS
51// ============================================================================
52// implementation
53// ============================================================================
54
24a23c35 55int wxTopLevelWindow::ms_drawDecorations = -1;
253293c1 56int wxTopLevelWindow::ms_canIconize = -1;
24a23c35 57
0f1bf77d
VS
58void wxTopLevelWindow::Init()
59{
a290fa5a 60 m_isActive = false;
ea1b0d6c 61 m_windowStyle = 0;
813edf09 62 m_pressedButton = 0;
0f1bf77d
VS
63}
64
65bool wxTopLevelWindow::Create(wxWindow *parent,
66 wxWindowID id,
67 const wxString& title,
68 const wxPoint& pos,
7ee7c43f 69 const wxSize& size,
0f1bf77d
VS
70 long style,
71 const wxString &name)
72{
2e9f62da
VZ
73 // init them to avoid compiler warnings
74 long styleOrig = 0,
75 exstyleOrig = 0;
24a23c35
VS
76
77 if ( ms_drawDecorations == -1 )
253293c1 78 {
1c067fe3
WS
79 ms_drawDecorations =
80 !wxSystemSettings::HasFeature(wxSYS_CAN_DRAW_FRAME_DECORATIONS)
253293c1 81 || wxGetEnv(wxT("WXDECOR"), NULL);
4c785218
VS
82 // FIXME -- wxUniv should provide a way to force non-native decorations!
83 // $WXDECOR is just a hack in absence of better wxUniv solution
253293c1
VS
84 }
85
86 if ( ms_canIconize == -1 )
87 {
7516ed26 88 ms_canIconize = wxSystemSettings::HasFeature(wxSYS_CAN_ICONIZE_FRAME);
253293c1 89 }
24a23c35
VS
90
91 if ( ms_drawDecorations )
92 {
ea1b0d6c
VS
93 CreateInputHandler(wxINP_HANDLER_TOPLEVEL);
94
24a23c35
VS
95 styleOrig = style;
96 exstyleOrig = GetExtraStyle();
7ee7c43f
VZ
97 style &= ~(wxCAPTION | wxMINIMIZE_BOX | wxMAXIMIZE_BOX |
98 wxSYSTEM_MENU | wxRESIZE_BORDER | wxFRAME_TOOL_WINDOW |
1c067fe3 99 wxRESIZE_BORDER);
999836aa 100 style |= wxSIMPLE_BORDER;
7ce6cc9b 101 SetExtraStyle(exstyleOrig & ~wxWS_EX_CONTEXTHELP);
24a23c35
VS
102 }
103
7ee7c43f
VZ
104 if ( !wxTopLevelWindowNative::Create(parent, id, title, pos,
105 size, style, name) )
a290fa5a 106 return false;
7ee7c43f 107
24a23c35
VS
108 if ( ms_drawDecorations )
109 {
110 m_windowStyle = styleOrig;
111 m_exStyle = exstyleOrig;
112 }
7ee7c43f 113
a290fa5a 114 return true;
0f1bf77d
VS
115}
116
117bool wxTopLevelWindow::ShowFullScreen(bool show, long style)
118{
a290fa5a 119 if ( show == IsFullScreen() ) return false;
7ee7c43f 120
ea1b0d6c
VS
121 if ( ms_drawDecorations )
122 {
123 if ( show )
124 {
125 m_fsSavedStyle = m_windowStyle;
126 if ( style & wxFULLSCREEN_NOBORDER )
127 m_windowStyle |= wxSIMPLE_BORDER;
128 if ( style & wxFULLSCREEN_NOCAPTION )
129 m_windowStyle &= ~wxCAPTION;
130 }
131 else
132 {
133 m_windowStyle = m_fsSavedStyle;
134 }
135 }
2e9f62da 136
ea1b0d6c 137 return wxTopLevelWindowNative::ShowFullScreen(show, style);
0f1bf77d
VS
138}
139
24a23c35
VS
140long wxTopLevelWindow::GetDecorationsStyle() const
141{
142 long style = 0;
143
144 if ( m_windowStyle & wxCAPTION )
145 {
ea1b0d6c 146 style |= wxTOPLEVEL_TITLEBAR | wxTOPLEVEL_BUTTON_CLOSE;
253293c1 147 if ( (m_windowStyle & wxMINIMIZE_BOX) && ms_canIconize )
813edf09 148 style |= wxTOPLEVEL_BUTTON_ICONIZE;
24a23c35 149 if ( m_windowStyle & wxMAXIMIZE_BOX )
15678bec
VS
150 {
151 if ( IsMaximized() )
152 style |= wxTOPLEVEL_BUTTON_RESTORE;
153 else
154 style |= wxTOPLEVEL_BUTTON_MAXIMIZE;
155 }
813edf09 156#if wxUSE_HELP
7ce6cc9b 157 if ( m_exStyle & wxWS_EX_CONTEXTHELP)
ea1b0d6c 158 style |= wxTOPLEVEL_BUTTON_HELP;
813edf09 159#endif
24a23c35
VS
160 }
161 if ( (m_windowStyle & (wxSIMPLE_BORDER | wxNO_BORDER)) == 0 )
162 style |= wxTOPLEVEL_BORDER;
1c067fe3 163 if ( m_windowStyle & (wxRESIZE_BORDER | wxRESIZE_BORDER) )
24a23c35 164 style |= wxTOPLEVEL_RESIZEABLE;
7ee7c43f 165
24a23c35
VS
166 if ( IsMaximized() )
167 style |= wxTOPLEVEL_MAXIMIZED;
168 if ( GetIcon().Ok() )
169 style |= wxTOPLEVEL_ICON;
ea1b0d6c 170 if ( m_isActive )
24a23c35
VS
171 style |= wxTOPLEVEL_ACTIVE;
172
173 return style;
174}
175
813edf09
VS
176void wxTopLevelWindow::RefreshTitleBar()
177{
178 wxNcPaintEvent event(GetId());
179 event.SetEventObject(this);
180 GetEventHandler()->ProcessEvent(event);
181}
182
24a23c35
VS
183// ----------------------------------------------------------------------------
184// client area handling
185// ----------------------------------------------------------------------------
186
187wxPoint wxTopLevelWindow::GetClientAreaOrigin() const
188{
189 if ( ms_drawDecorations )
190 {
191 int w, h;
192 wxTopLevelWindowNative::DoGetClientSize(&w, &h);
193 wxRect rect = wxRect(wxTopLevelWindowNative::GetClientAreaOrigin(),
194 wxSize(w, h));
7ee7c43f 195 rect = m_renderer->GetFrameClientArea(rect,
24a23c35
VS
196 GetDecorationsStyle());
197 return rect.GetPosition();
198 }
199 else
200 {
201 return wxTopLevelWindowNative::GetClientAreaOrigin();
202 }
203}
204
205void wxTopLevelWindow::DoGetClientSize(int *width, int *height) const
206{
207 if ( ms_drawDecorations )
208 {
209 int w, h;
210 wxTopLevelWindowNative::DoGetClientSize(&w, &h);
211 wxRect rect = wxRect(wxTopLevelWindowNative::GetClientAreaOrigin(),
212 wxSize(w, h));
7ee7c43f 213 rect = m_renderer->GetFrameClientArea(rect,
24a23c35
VS
214 GetDecorationsStyle());
215 if ( width )
216 *width = rect.width;
217 if ( height )
218 *height = rect.height;
219 }
220 else
221 wxTopLevelWindowNative::DoGetClientSize(width, height);
222}
223
224void wxTopLevelWindow::DoSetClientSize(int width, int height)
225{
226 if ( ms_drawDecorations )
227 {
7ee7c43f 228 wxSize size = m_renderer->GetFrameTotalSize(wxSize(width, height),
24a23c35
VS
229 GetDecorationsStyle());
230 wxTopLevelWindowNative::DoSetClientSize(size.x, size.y);
231 }
232 else
233 wxTopLevelWindowNative::DoSetClientSize(width, height);
234}
235
3795cdba 236void wxTopLevelWindow::OnNcPaint(wxNcPaintEvent& event)
24a23c35
VS
237{
238 if ( !ms_drawDecorations || !m_renderer )
239 event.Skip();
240 else
241 {
242 // get the window rect
9a6384ca 243 wxRect rect(GetSize());
24a23c35
VS
244
245 wxWindowDC dc(this);
7ee7c43f 246 m_renderer->DrawFrameTitleBar(dc, rect,
24a23c35 247 GetTitle(), m_titlebarIcon,
813edf09
VS
248 GetDecorationsStyle(),
249 m_pressedButton,
250 wxCONTROL_PRESSED);
24a23c35
VS
251 }
252}
253
813edf09
VS
254long wxTopLevelWindow::HitTest(const wxPoint& pt) const
255{
256 int w, h;
257 wxTopLevelWindowNative::DoGetClientSize(&w, &h);
258 wxRect rect(wxTopLevelWindowNative::GetClientAreaOrigin(), wxSize(w, h));
7ee7c43f 259
badc44fe 260 return m_renderer->HitTestFrame(rect, pt+GetClientAreaOrigin(), GetDecorationsStyle());
813edf09
VS
261}
262
e7dda1ff
VS
263int wxTopLevelWindow::GetMinWidth() const
264{
265 if ( ms_drawDecorations )
266 {
267 return wxMax(wxTopLevelWindowNative::GetMinWidth(),
268 m_renderer->GetFrameMinSize(GetDecorationsStyle()).x);
269 }
270 else
271 return wxTopLevelWindowNative::GetMinWidth();
272}
273
274int wxTopLevelWindow::GetMinHeight() const
275{
276 if ( ms_drawDecorations )
277 {
278 return wxMax(wxTopLevelWindowNative::GetMinHeight(),
279 m_renderer->GetFrameMinSize(GetDecorationsStyle()).y);
280 }
281 else
282 return wxTopLevelWindowNative::GetMinHeight();
283}
284
24a23c35
VS
285// ----------------------------------------------------------------------------
286// icons
287// ----------------------------------------------------------------------------
288
f618020a 289void wxTopLevelWindow::SetIcons(const wxIconBundle& icons)
24a23c35 290{
f618020a 291 wxTopLevelWindowNative::SetIcons(icons);
24a23c35 292
15678bec 293 if ( ms_drawDecorations && m_renderer )
24a23c35 294 {
15678bec 295 wxSize size = m_renderer->GetFrameIconSize();
f618020a 296 const wxIcon& icon = icons.GetIcon( size );
15678bec 297
a290fa5a 298 if ( !icon.Ok() || size.x == wxDefaultCoord )
24a23c35
VS
299 m_titlebarIcon = icon;
300 else
301 {
15678bec
VS
302 wxBitmap bmp1;
303 bmp1.CopyFromIcon(icon);
304 if ( !bmp1.Ok() )
305 m_titlebarIcon = wxNullIcon;
306 else if ( bmp1.GetWidth() == size.x && bmp1.GetHeight() == size.y )
307 m_titlebarIcon = icon;
9a6384ca 308#if wxUSE_IMAGE
15678bec
VS
309 else
310 {
311 wxImage img = bmp1.ConvertToImage();
312 img.Rescale(size.x, size.y);
313 m_titlebarIcon.CopyFromBitmap(wxBitmap(img));
314 }
9a6384ca 315#endif // wxUSE_IMAGE
24a23c35
VS
316 }
317 }
318}
ea1b0d6c 319
621b405f
VS
320// ----------------------------------------------------------------------------
321// interactive manipulation
322// ----------------------------------------------------------------------------
323
b53195fd
VS
324
325static bool wxGetResizingCursor(long hitTestResult, wxCursor& cursor)
326{
327 if ( hitTestResult & wxHT_TOPLEVEL_ANY_BORDER )
328 {
329 switch (hitTestResult)
330 {
331 case wxHT_TOPLEVEL_BORDER_N:
332 case wxHT_TOPLEVEL_BORDER_S:
333 cursor = wxCursor(wxCURSOR_SIZENS);
334 break;
335 case wxHT_TOPLEVEL_BORDER_W:
336 case wxHT_TOPLEVEL_BORDER_E:
337 cursor = wxCursor(wxCURSOR_SIZEWE);
338 break;
339 case wxHT_TOPLEVEL_BORDER_NE:
340 case wxHT_TOPLEVEL_BORDER_SW:
341 cursor = wxCursor(wxCURSOR_SIZENESW);
342 break;
343 case wxHT_TOPLEVEL_BORDER_NW:
344 case wxHT_TOPLEVEL_BORDER_SE:
345 cursor = wxCursor(wxCURSOR_SIZENWSE);
346 break;
347 default:
a290fa5a 348 return false;
b53195fd 349 }
a290fa5a 350 return true;
b53195fd 351 }
1c067fe3 352
a290fa5a 353 return false;
b53195fd
VS
354}
355
621b405f
VS
356#define wxINTERACTIVE_RESIZE_DIR \
357 (wxINTERACTIVE_RESIZE_W | wxINTERACTIVE_RESIZE_E | \
358 wxINTERACTIVE_RESIZE_S | wxINTERACTIVE_RESIZE_N)
359
360struct wxInteractiveMoveData
361{
b53195fd 362 wxTopLevelWindow *m_window;
621b405f
VS
363 wxEventLoop *m_evtLoop;
364 int m_flags;
365 wxRect m_rect;
366 wxRect m_rectOrig;
367 wxPoint m_pos;
368 wxSize m_minSize, m_maxSize;
71cb2ca1 369 bool m_sizingCursor;
621b405f
VS
370};
371
372class wxInteractiveMoveHandler : public wxEvtHandler
373{
374public:
375 wxInteractiveMoveHandler(wxInteractiveMoveData& data) : m_data(data) {}
1c067fe3 376
621b405f
VS
377private:
378 DECLARE_EVENT_TABLE()
379 void OnMouseMove(wxMouseEvent& event);
380 void OnMouseDown(wxMouseEvent& event);
381 void OnMouseUp(wxMouseEvent& event);
382 void OnKeyDown(wxKeyEvent& event);
383
384 wxInteractiveMoveData& m_data;
385};
386
387BEGIN_EVENT_TABLE(wxInteractiveMoveHandler, wxEvtHandler)
388 EVT_MOTION(wxInteractiveMoveHandler::OnMouseMove)
389 EVT_LEFT_DOWN(wxInteractiveMoveHandler::OnMouseDown)
390 EVT_LEFT_UP(wxInteractiveMoveHandler::OnMouseUp)
391 EVT_KEY_DOWN(wxInteractiveMoveHandler::OnKeyDown)
392END_EVENT_TABLE()
393
394
1c067fe3 395static inline LINKAGEMODE
621b405f
VS
396void wxApplyResize(wxInteractiveMoveData& data, const wxPoint& diff)
397{
398 if ( data.m_flags & wxINTERACTIVE_RESIZE_W )
399 {
400 data.m_rect.x += diff.x;
401 data.m_rect.width -= diff.x;
402 }
403 else if ( data.m_flags & wxINTERACTIVE_RESIZE_E )
404 {
405 data.m_rect.width += diff.x;
406 }
407 if ( data.m_flags & wxINTERACTIVE_RESIZE_N )
408 {
409 data.m_rect.y += diff.y;
410 data.m_rect.height -= diff.y;
411 }
412 else if ( data.m_flags & wxINTERACTIVE_RESIZE_S )
413 {
414 data.m_rect.height += diff.y;
415 }
1c067fe3 416
a290fa5a 417 if ( data.m_minSize.x != wxDefaultCoord && data.m_rect.width < data.m_minSize.x )
621b405f
VS
418 {
419 if ( data.m_flags & wxINTERACTIVE_RESIZE_W )
420 data.m_rect.x -= data.m_minSize.x - data.m_rect.width;
421 data.m_rect.width = data.m_minSize.x;
422 }
a290fa5a 423 if ( data.m_maxSize.x != wxDefaultCoord && data.m_rect.width > data.m_maxSize.x )
621b405f
VS
424 {
425 if ( data.m_flags & wxINTERACTIVE_RESIZE_W )
426 data.m_rect.x -= data.m_minSize.x - data.m_rect.width;
427 data.m_rect.width = data.m_maxSize.x;
428 }
a290fa5a 429 if ( data.m_minSize.y != wxDefaultCoord && data.m_rect.height < data.m_minSize.y )
621b405f
VS
430 {
431 if ( data.m_flags & wxINTERACTIVE_RESIZE_N )
432 data.m_rect.y -= data.m_minSize.y - data.m_rect.height;
433 data.m_rect.height = data.m_minSize.y;
434 }
a290fa5a 435 if ( data.m_maxSize.y != wxDefaultCoord && data.m_rect.height > data.m_maxSize.y )
621b405f
VS
436 {
437 if ( data.m_flags & wxINTERACTIVE_RESIZE_N )
438 data.m_rect.y -= data.m_minSize.y - data.m_rect.height;
439 data.m_rect.height = data.m_maxSize.y;
440 }
441}
442
443void wxInteractiveMoveHandler::OnMouseMove(wxMouseEvent& event)
444{
445 if ( m_data.m_flags & wxINTERACTIVE_WAIT_FOR_INPUT )
446 event.Skip();
447
448 else if ( m_data.m_flags & wxINTERACTIVE_MOVE )
449 {
450 wxPoint diff = wxGetMousePosition() - m_data.m_pos;
451 m_data.m_rect = m_data.m_rectOrig;
452 m_data.m_rect.Offset(diff);
453 m_data.m_window->Move(m_data.m_rect.GetPosition());
454 }
455
456 else if ( m_data.m_flags & wxINTERACTIVE_RESIZE )
457 {
458 wxPoint diff = wxGetMousePosition() - m_data.m_pos;
459 m_data.m_rect = m_data.m_rectOrig;
460 wxApplyResize(m_data, diff);
461 m_data.m_window->SetSize(m_data.m_rect);
462 }
463}
464
61fef19b 465void wxInteractiveMoveHandler::OnMouseDown(wxMouseEvent& WXUNUSED(event))
621b405f
VS
466{
467 if ( m_data.m_flags & wxINTERACTIVE_WAIT_FOR_INPUT )
468 {
71cb2ca1 469 m_data.m_evtLoop->Exit();
621b405f
VS
470 }
471}
472
473void wxInteractiveMoveHandler::OnKeyDown(wxKeyEvent& event)
474{
a290fa5a 475 wxPoint diff(wxDefaultCoord,wxDefaultCoord);
1c067fe3 476
621b405f
VS
477 switch ( event.GetKeyCode() )
478 {
479 case WXK_UP: diff = wxPoint(0, -16); break;
480 case WXK_DOWN: diff = wxPoint(0, 16); break;
481 case WXK_LEFT: diff = wxPoint(-16, 0); break;
482 case WXK_RIGHT: diff = wxPoint(16, 0); break;
483 case WXK_ESCAPE:
484 m_data.m_window->SetSize(m_data.m_rectOrig);
485 m_data.m_evtLoop->Exit();
486 return;
487 case WXK_RETURN:
488 m_data.m_evtLoop->Exit();
489 return;
490 }
1c067fe3 491
a290fa5a 492 if ( diff.x != wxDefaultCoord )
621b405f 493 {
71cb2ca1
VS
494 if ( m_data.m_flags & wxINTERACTIVE_WAIT_FOR_INPUT )
495 {
496 m_data.m_flags &= ~wxINTERACTIVE_WAIT_FOR_INPUT;
497 if ( m_data.m_sizingCursor )
498 {
499 wxEndBusyCursor();
a290fa5a 500 m_data.m_sizingCursor = false;
71cb2ca1
VS
501 }
502
503 if ( m_data.m_flags & wxINTERACTIVE_MOVE )
504 {
1c067fe3 505 m_data.m_pos = m_data.m_window->GetPosition() +
71cb2ca1
VS
506 wxPoint(m_data.m_window->GetSize().x/2, 8);
507 }
508 }
509
510 wxPoint warp;
a290fa5a 511 bool changeCur = false;
1c067fe3 512
621b405f
VS
513 if ( m_data.m_flags & wxINTERACTIVE_MOVE )
514 {
515 m_data.m_rect.Offset(diff);
516 m_data.m_window->Move(m_data.m_rect.GetPosition());
71cb2ca1 517 warp = wxPoint(m_data.m_window->GetSize().x/2, 8);
621b405f
VS
518 }
519 else /* wxINTERACTIVE_RESIZE */
520 {
1c067fe3 521 if ( !(m_data.m_flags &
71cb2ca1 522 (wxINTERACTIVE_RESIZE_N | wxINTERACTIVE_RESIZE_S)) )
621b405f
VS
523 {
524 if ( diff.y < 0 )
71cb2ca1 525 {
621b405f 526 m_data.m_flags |= wxINTERACTIVE_RESIZE_N;
71cb2ca1 527 m_data.m_pos.y = m_data.m_window->GetPosition().y;
a290fa5a 528 changeCur = true;
71cb2ca1 529 }
621b405f 530 else if ( diff.y > 0 )
71cb2ca1 531 {
621b405f 532 m_data.m_flags |= wxINTERACTIVE_RESIZE_S;
71cb2ca1
VS
533 m_data.m_pos.y = m_data.m_window->GetPosition().y +
534 m_data.m_window->GetSize().y;
a290fa5a 535 changeCur = true;
71cb2ca1
VS
536 }
537 }
1c067fe3 538 if ( !(m_data.m_flags &
71cb2ca1
VS
539 (wxINTERACTIVE_RESIZE_W | wxINTERACTIVE_RESIZE_E)) )
540 {
621b405f 541 if ( diff.x < 0 )
71cb2ca1 542 {
621b405f 543 m_data.m_flags |= wxINTERACTIVE_RESIZE_W;
71cb2ca1 544 m_data.m_pos.x = m_data.m_window->GetPosition().x;
a290fa5a 545 changeCur = true;
71cb2ca1 546 }
621b405f 547 else if ( diff.x > 0 )
71cb2ca1 548 {
621b405f 549 m_data.m_flags |= wxINTERACTIVE_RESIZE_E;
71cb2ca1
VS
550 m_data.m_pos.x = m_data.m_window->GetPosition().x +
551 m_data.m_window->GetSize().x;
a290fa5a 552 changeCur = true;
71cb2ca1 553 }
621b405f 554 }
b53195fd 555
621b405f
VS
556 wxApplyResize(m_data, diff);
557 m_data.m_window->SetSize(m_data.m_rect);
71cb2ca1
VS
558
559 if ( m_data.m_flags & wxINTERACTIVE_RESIZE_W )
560 warp.x = 0;
561 else if ( m_data.m_flags & wxINTERACTIVE_RESIZE_E )
562 warp.x = m_data.m_window->GetSize().x-1;
563 else
564 warp.x = wxGetMousePosition().x - m_data.m_window->GetPosition().x;
565
566 if ( m_data.m_flags & wxINTERACTIVE_RESIZE_N )
567 warp.y = 0;
568 else if ( m_data.m_flags & wxINTERACTIVE_RESIZE_S )
569 warp.y = m_data.m_window->GetSize().y-1;
570 else
571 warp.y = wxGetMousePosition().y - m_data.m_window->GetPosition().y;
621b405f 572 }
71cb2ca1
VS
573
574 warp -= m_data.m_window->GetClientAreaOrigin();
575 m_data.m_window->WarpPointer(warp.x, warp.y);
b53195fd
VS
576
577 if ( changeCur )
578 {
579 long hit = m_data.m_window->HitTest(warp);
580 wxCursor cur;
581 if ( wxGetResizingCursor(hit, cur) )
582 {
583 if ( m_data.m_sizingCursor )
584 wxEndBusyCursor();
585 wxBeginBusyCursor(&cur);
a290fa5a 586 m_data.m_sizingCursor = true;
b53195fd
VS
587 }
588 }
621b405f
VS
589 }
590}
591
61fef19b 592void wxInteractiveMoveHandler::OnMouseUp(wxMouseEvent& WXUNUSED(event))
621b405f
VS
593{
594 m_data.m_evtLoop->Exit();
595}
596
597
598void wxTopLevelWindow::InteractiveMove(int flags)
599{
600 wxASSERT_MSG( !((flags & wxINTERACTIVE_MOVE) && (flags & wxINTERACTIVE_RESIZE)),
601 wxT("can't move and resize window at the same time") );
602
1c067fe3
WS
603 wxASSERT_MSG( !(flags & wxINTERACTIVE_RESIZE) ||
604 (flags & wxINTERACTIVE_WAIT_FOR_INPUT) ||
621b405f
VS
605 (flags & wxINTERACTIVE_RESIZE_DIR),
606 wxT("direction of resizing not specified") );
607
608 wxInteractiveMoveData data;
609 wxEventLoop loop;
1c067fe3 610
71cb2ca1
VS
611 SetFocus();
612
1c067fe3 613#ifndef __WXGTK__
71cb2ca1
VS
614 if ( flags & wxINTERACTIVE_WAIT_FOR_INPUT )
615 {
616 wxCursor sizingCursor(wxCURSOR_SIZING);
617 wxBeginBusyCursor(&sizingCursor);
a290fa5a 618 data.m_sizingCursor = true;
71cb2ca1
VS
619 }
620 else
621#endif
a290fa5a 622 data.m_sizingCursor = false;
621b405f
VS
623
624 data.m_window = this;
625 data.m_evtLoop = &loop;
626 data.m_flags = flags;
627 data.m_rect = data.m_rectOrig = GetRect();
628 data.m_pos = wxGetMousePosition();
629 data.m_minSize = wxSize(GetMinWidth(), GetMinHeight());
630 data.m_maxSize = wxSize(GetMaxWidth(), GetMaxHeight());
631
71cb2ca1
VS
632 wxEvtHandler *handler = new wxInteractiveMoveHandler(data);
633 this->PushEventHandler(handler);
621b405f
VS
634
635 CaptureMouse();
636 loop.Run();
637 ReleaseMouse();
638
71cb2ca1
VS
639 this->RemoveEventHandler(handler);
640 delete handler;
641
642 if ( data.m_sizingCursor )
643 wxEndBusyCursor();
621b405f
VS
644}
645
ea1b0d6c
VS
646// ----------------------------------------------------------------------------
647// actions
648// ----------------------------------------------------------------------------
649
813edf09
VS
650void wxTopLevelWindow::ClickTitleBarButton(long button)
651{
652 switch ( button )
653 {
654 case wxTOPLEVEL_BUTTON_CLOSE:
655 Close();
656 break;
657
658 case wxTOPLEVEL_BUTTON_ICONIZE:
659 Iconize();
660 break;
661
662 case wxTOPLEVEL_BUTTON_MAXIMIZE:
663 Maximize();
664 break;
665
666 case wxTOPLEVEL_BUTTON_RESTORE:
667 Restore();
668 break;
669
670 case wxTOPLEVEL_BUTTON_HELP:
671#if wxUSE_HELP
672 {
673 wxContextHelp contextHelp(this);
674 }
675#endif
676 break;
7ee7c43f 677
813edf09
VS
678 default:
679 wxFAIL_MSG(wxT("incorrect button specification"));
680 }
681}
682
ea1b0d6c
VS
683bool wxTopLevelWindow::PerformAction(const wxControlAction& action,
684 long numArg,
61fef19b 685 const wxString& WXUNUSED(strArg))
ea1b0d6c 686{
7ee7c43f
VZ
687 bool isActive = numArg != 0;
688
ea1b0d6c
VS
689 if ( action == wxACTION_TOPLEVEL_ACTIVATE )
690 {
7ee7c43f 691 if ( m_isActive != isActive )
ea1b0d6c 692 {
7ee7c43f 693 m_isActive = isActive;
b22d16ad 694 RefreshTitleBar();
ea1b0d6c 695 }
a290fa5a 696 return true;
ea1b0d6c 697 }
7ee7c43f 698
813edf09
VS
699 else if ( action == wxACTION_TOPLEVEL_BUTTON_PRESS )
700 {
701 m_pressedButton = numArg;
702 RefreshTitleBar();
a290fa5a 703 return true;
813edf09 704 }
7ee7c43f 705
813edf09
VS
706 else if ( action == wxACTION_TOPLEVEL_BUTTON_RELEASE )
707 {
708 m_pressedButton = 0;
709 RefreshTitleBar();
a290fa5a 710 return true;
813edf09 711 }
7ee7c43f 712
813edf09
VS
713 else if ( action == wxACTION_TOPLEVEL_BUTTON_CLICK )
714 {
715 m_pressedButton = 0;
716 RefreshTitleBar();
717 ClickTitleBarButton(numArg);
a290fa5a 718 return true;
813edf09 719 }
71e03035 720
b22d16ad
VS
721 else if ( action == wxACTION_TOPLEVEL_MOVE )
722 {
723 InteractiveMove(wxINTERACTIVE_MOVE);
a290fa5a 724 return true;
b22d16ad 725 }
71e03035 726
b22d16ad
VS
727 else if ( action == wxACTION_TOPLEVEL_RESIZE )
728 {
729 int flags = wxINTERACTIVE_RESIZE;
730 if ( numArg & wxHT_TOPLEVEL_BORDER_N )
731 flags |= wxINTERACTIVE_RESIZE_N;
732 if ( numArg & wxHT_TOPLEVEL_BORDER_S )
733 flags |= wxINTERACTIVE_RESIZE_S;
734 if ( numArg & wxHT_TOPLEVEL_BORDER_W )
735 flags |= wxINTERACTIVE_RESIZE_W;
736 if ( numArg & wxHT_TOPLEVEL_BORDER_E )
737 flags |= wxINTERACTIVE_RESIZE_E;
738 InteractiveMove(flags);
a290fa5a 739 return true;
b22d16ad 740 }
71e03035 741
ea1b0d6c 742 else
a290fa5a 743 return false;
ea1b0d6c
VS
744}
745
71cb2ca1
VS
746void wxTopLevelWindow::OnSystemMenu(wxCommandEvent& event)
747{
a290fa5a 748 bool ret = true;
1c067fe3 749
71cb2ca1
VS
750 switch (event.GetId())
751 {
752 case wxID_CLOSE_FRAME:
753 ret = PerformAction(wxACTION_TOPLEVEL_BUTTON_CLICK,
754 wxTOPLEVEL_BUTTON_CLOSE);
755 break;
756 case wxID_MOVE_FRAME:
757 InteractiveMove(wxINTERACTIVE_MOVE | wxINTERACTIVE_WAIT_FOR_INPUT);
758 break;
759 case wxID_RESIZE_FRAME:
760 InteractiveMove(wxINTERACTIVE_RESIZE | wxINTERACTIVE_WAIT_FOR_INPUT);
761 break;
762 case wxID_MAXIMIZE_FRAME:
763 ret = PerformAction(wxACTION_TOPLEVEL_BUTTON_CLICK,
764 wxTOPLEVEL_BUTTON_MAXIMIZE);
765 break;
766 case wxID_ICONIZE_FRAME:
767 ret = PerformAction(wxACTION_TOPLEVEL_BUTTON_CLICK,
768 wxTOPLEVEL_BUTTON_ICONIZE);
769 break;
770 case wxID_RESTORE_FRAME:
771 ret = PerformAction(wxACTION_TOPLEVEL_BUTTON_CLICK,
772 wxTOPLEVEL_BUTTON_RESTORE);
773 break;
774
775 default:
a290fa5a 776 ret = false;
71cb2ca1 777 }
1c067fe3 778
71cb2ca1
VS
779 if ( !ret )
780 event.Skip();
781}
782
ea1b0d6c
VS
783
784// ============================================================================
785// wxStdFrameInputHandler: handles focus, resizing and titlebar buttons clicks
786// ============================================================================
787
788wxStdFrameInputHandler::wxStdFrameInputHandler(wxInputHandler *inphand)
789 : wxStdInputHandler(inphand)
790{
813edf09
VS
791 m_winCapture = NULL;
792 m_winHitTest = 0;
793 m_winPressed = 0;
a290fa5a 794 m_borderCursorOn = false;
ea1b0d6c
VS
795}
796
797bool wxStdFrameInputHandler::HandleMouse(wxInputConsumer *consumer,
798 const wxMouseEvent& event)
799{
813edf09
VS
800 // the button has 2 states: pressed and normal with the following
801 // transitions between them:
802 //
803 // normal -> left down -> capture mouse and go to pressed state
804 // pressed -> left up inside -> generate click -> go to normal
805 // outside ------------------>
806 //
807 // the other mouse buttons are ignored
808 if ( event.Button(1) )
809 {
810 if ( event.ButtonDown(1) )
811 {
812 wxTopLevelWindow *w = wxStaticCast(consumer->GetInputWindow(), wxTopLevelWindow);
813 long hit = w->HitTest(event.GetPosition());
7ee7c43f 814
813edf09
VS
815 if ( hit & wxHT_TOPLEVEL_ANY_BUTTON )
816 {
817 m_winCapture = w;
818 m_winCapture->CaptureMouse();
819 m_winHitTest = hit;
820 m_winPressed = hit;
821 consumer->PerformAction(wxACTION_TOPLEVEL_BUTTON_PRESS, m_winPressed);
a290fa5a 822 return true;
813edf09 823 }
aa74396d 824 else if ( (hit & wxHT_TOPLEVEL_TITLEBAR) && !w->IsMaximized() )
b22d16ad
VS
825 {
826 consumer->PerformAction(wxACTION_TOPLEVEL_MOVE);
a290fa5a 827 return true;
b22d16ad
VS
828 }
829 else if ( (consumer->GetInputWindow()->GetWindowStyle() & wxRESIZE_BORDER)
830 && (hit & wxHT_TOPLEVEL_ANY_BORDER) )
831 {
832 consumer->PerformAction(wxACTION_TOPLEVEL_RESIZE, hit);
a290fa5a 833 return true;
b22d16ad 834 }
813edf09
VS
835 }
836
837 else // up
838 {
839 if ( m_winCapture )
840 {
841 m_winCapture->ReleaseMouse();
842 m_winCapture = NULL;
843
844 if ( m_winHitTest == m_winPressed )
845 {
846 consumer->PerformAction(wxACTION_TOPLEVEL_BUTTON_CLICK, m_winPressed);
a290fa5a 847 return true;
813edf09
VS
848 }
849 }
850 //else: the mouse was released outside the window, this doesn't
851 // count as a click
852 }
853 }
854
ea1b0d6c
VS
855 return wxStdInputHandler::HandleMouse(consumer, event);
856}
857
7ee7c43f 858bool wxStdFrameInputHandler::HandleMouseMove(wxInputConsumer *consumer,
ea1b0d6c
VS
859 const wxMouseEvent& event)
860{
813edf09
VS
861 if ( event.GetEventObject() == m_winCapture )
862 {
863 long hit = m_winCapture->HitTest(event.GetPosition());
864
865 if ( hit != m_winHitTest )
866 {
867 if ( hit != m_winPressed )
868 consumer->PerformAction(wxACTION_TOPLEVEL_BUTTON_RELEASE, m_winPressed);
869 else
870 consumer->PerformAction(wxACTION_TOPLEVEL_BUTTON_PRESS, m_winPressed);
7ee7c43f 871
813edf09 872 m_winHitTest = hit;
a290fa5a 873 return true;
813edf09
VS
874 }
875 }
b22d16ad
VS
876 else if ( consumer->GetInputWindow()->GetWindowStyle() & wxRESIZE_BORDER )
877 {
71e03035 878 wxTopLevelWindow *win = wxStaticCast(consumer->GetInputWindow(),
b22d16ad
VS
879 wxTopLevelWindow);
880 long hit = win->HitTest(event.GetPosition());
71e03035 881
b22d16ad
VS
882 if ( hit != m_winHitTest )
883 {
884 m_winHitTest = hit;
71e03035 885
b22d16ad
VS
886 if ( m_borderCursorOn )
887 {
a290fa5a 888 m_borderCursorOn = false;
b22d16ad
VS
889 win->SetCursor(m_origCursor);
890 }
71e03035 891
b22d16ad
VS
892 if ( hit & wxHT_TOPLEVEL_ANY_BORDER )
893 {
b22d16ad 894 wxCursor cur;
71e03035 895
b53195fd 896 m_borderCursorOn = wxGetResizingCursor(hit, cur);
b22d16ad
VS
897 if ( m_borderCursorOn )
898 {
899 m_origCursor = win->GetCursor();
900 win->SetCursor(cur);
901 }
902 }
903 }
904 }
813edf09 905
ea1b0d6c
VS
906 return wxStdInputHandler::HandleMouseMove(consumer, event);
907}
908
7ee7c43f 909bool wxStdFrameInputHandler::HandleActivation(wxInputConsumer *consumer,
ea1b0d6c
VS
910 bool activated)
911{
b22d16ad
VS
912 if ( m_borderCursorOn )
913 {
914 consumer->GetInputWindow()->SetCursor(m_origCursor);
a290fa5a 915 m_borderCursorOn = false;
b22d16ad 916 }
ea1b0d6c 917 consumer->PerformAction(wxACTION_TOPLEVEL_ACTIVATE, activated);
a290fa5a 918 return false;
ea1b0d6c 919}