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