respect minimal wxTLW size in wxUniv
[wxWidgets.git] / src / univ / topluniv.cpp
1 /////////////////////////////////////////////////////////////////////////////
2 // Name: topluniv.cpp
3 // Author: Vaclav Slavik
4 // Id: $Id$
5 // Copyright: (c) 2001 SciTech Software, Inc. (www.scitechsoft.com)
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"
29
30 #ifndef WX_PRECOMP
31 #include "wx/dcclient.h"
32 #include "wx/settings.h"
33 #endif
34
35 #include "wx/toplevel.h"
36 #include "wx/univ/renderer.h"
37 #include "wx/bitmap.h"
38 #include "wx/image.h"
39 #include "wx/cshelp.h"
40 #include "wx/evtloop.h"
41
42
43 // ----------------------------------------------------------------------------
44 // event tables
45 // ----------------------------------------------------------------------------
46
47 BEGIN_EVENT_TABLE(wxTopLevelWindow, wxTopLevelWindowNative)
48 WX_EVENT_TABLE_INPUT_CONSUMER(wxTopLevelWindow)
49 EVT_NC_PAINT(wxTopLevelWindow::OnNcPaint)
50 END_EVENT_TABLE()
51
52 WX_FORWARD_TO_INPUT_CONSUMER(wxTopLevelWindow)
53
54 // ============================================================================
55 // implementation
56 // ============================================================================
57
58 int wxTopLevelWindow::ms_drawDecorations = -1;
59 int wxTopLevelWindow::ms_canIconize = -1;
60
61 void wxTopLevelWindow::Init()
62 {
63 m_isActive = FALSE;
64 m_windowStyle = 0;
65 m_pressedButton = 0;
66 }
67
68 bool wxTopLevelWindow::Create(wxWindow *parent,
69 wxWindowID id,
70 const wxString& title,
71 const wxPoint& pos,
72 const wxSize& size,
73 long style,
74 const wxString &name)
75 {
76 // init them to avoid compiler warnings
77 long styleOrig = 0,
78 exstyleOrig = 0;
79
80 if ( ms_drawDecorations == -1 )
81 {
82 ms_drawDecorations =
83 !wxSystemSettings::HasFeature(wxSYS_CAN_DRAW_FRAME_DECORATIONS)
84 || wxGetEnv(wxT("WXDECOR"), NULL);
85 // FIXME -- wxUniv should provide a way to force non-native decorations!
86 // $WXDECOR is just a hack in absence of better wxUniv solution
87 }
88
89 if ( ms_canIconize == -1 )
90 {
91 ms_canIconize = wxSystemSettings::HasFeature(wxSYS_CAN_ICONIZE_FRAME);
92 }
93
94 if ( ms_drawDecorations )
95 {
96 CreateInputHandler(wxINP_HANDLER_TOPLEVEL);
97
98 styleOrig = style;
99 exstyleOrig = GetExtraStyle();
100 style &= ~(wxCAPTION | wxMINIMIZE_BOX | wxMAXIMIZE_BOX |
101 wxSYSTEM_MENU | wxRESIZE_BORDER | wxFRAME_TOOL_WINDOW |
102 wxTHICK_FRAME);
103 style = wxSIMPLE_BORDER;
104 SetExtraStyle(exstyleOrig &
105 ~(wxFRAME_EX_CONTEXTHELP | wxDIALOG_EX_CONTEXTHELP));
106 }
107
108 if ( !wxTopLevelWindowNative::Create(parent, id, title, pos,
109 size, style, name) )
110 return FALSE;
111
112 if ( ms_drawDecorations )
113 {
114 m_windowStyle = styleOrig;
115 m_exStyle = exstyleOrig;
116 }
117
118 return TRUE;
119 }
120
121 bool wxTopLevelWindow::ShowFullScreen(bool show, long style)
122 {
123 if ( show == IsFullScreen() ) return FALSE;
124
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 }
140
141 return wxTopLevelWindowNative::ShowFullScreen(show, style);
142 }
143
144 long wxTopLevelWindow::GetDecorationsStyle() const
145 {
146 long style = 0;
147
148 if ( m_windowStyle & wxCAPTION )
149 {
150 style |= wxTOPLEVEL_TITLEBAR | wxTOPLEVEL_BUTTON_CLOSE;
151 if ( (m_windowStyle & wxMINIMIZE_BOX) && ms_canIconize )
152 style |= wxTOPLEVEL_BUTTON_ICONIZE;
153 if ( m_windowStyle & wxMAXIMIZE_BOX )
154 {
155 if ( IsMaximized() )
156 style |= wxTOPLEVEL_BUTTON_RESTORE;
157 else
158 style |= wxTOPLEVEL_BUTTON_MAXIMIZE;
159 }
160 #if wxUSE_HELP
161 if ( m_exStyle & (wxFRAME_EX_CONTEXTHELP | wxDIALOG_EX_CONTEXTHELP))
162 style |= wxTOPLEVEL_BUTTON_HELP;
163 #endif
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;
169
170 if ( IsMaximized() )
171 style |= wxTOPLEVEL_MAXIMIZED;
172 if ( GetIcon().Ok() )
173 style |= wxTOPLEVEL_ICON;
174 if ( m_isActive )
175 style |= wxTOPLEVEL_ACTIVE;
176
177 return style;
178 }
179
180 void wxTopLevelWindow::RefreshTitleBar()
181 {
182 wxNcPaintEvent event(GetId());
183 event.SetEventObject(this);
184 GetEventHandler()->ProcessEvent(event);
185 }
186
187 // ----------------------------------------------------------------------------
188 // client area handling
189 // ----------------------------------------------------------------------------
190
191 wxPoint 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));
199 rect = m_renderer->GetFrameClientArea(rect,
200 GetDecorationsStyle());
201 return rect.GetPosition();
202 }
203 else
204 {
205 return wxTopLevelWindowNative::GetClientAreaOrigin();
206 }
207 }
208
209 void 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));
217 rect = m_renderer->GetFrameClientArea(rect,
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
228 void wxTopLevelWindow::DoSetClientSize(int width, int height)
229 {
230 if ( ms_drawDecorations )
231 {
232 wxSize size = m_renderer->GetFrameTotalSize(wxSize(width, height),
233 GetDecorationsStyle());
234 wxTopLevelWindowNative::DoSetClientSize(size.x, size.y);
235 }
236 else
237 wxTopLevelWindowNative::DoSetClientSize(width, height);
238 }
239
240 void 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);
255 m_renderer->DrawFrameTitleBar(dc, rect,
256 GetTitle(), m_titlebarIcon,
257 GetDecorationsStyle(),
258 m_pressedButton,
259 wxCONTROL_PRESSED);
260 }
261 }
262
263 long wxTopLevelWindow::HitTest(const wxPoint& pt) const
264 {
265 int w, h;
266 wxTopLevelWindowNative::DoGetClientSize(&w, &h);
267 wxRect rect(wxTopLevelWindowNative::GetClientAreaOrigin(), wxSize(w, h));
268
269 return m_renderer->HitTestFrame(rect, pt+GetClientAreaOrigin(), GetDecorationsStyle());
270 }
271
272 int 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
283 int 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
294 // ----------------------------------------------------------------------------
295 // icons
296 // ----------------------------------------------------------------------------
297
298 void wxTopLevelWindow::SetIcon(const wxIcon& icon)
299 {
300 wxTopLevelWindowNative::SetIcon(icon);
301
302 if ( ms_drawDecorations && m_renderer )
303 {
304 wxSize size = m_renderer->GetFrameIconSize();
305
306 if ( !icon.Ok() || size.x == -1 )
307 m_titlebarIcon = icon;
308 else
309 {
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 }
322 }
323 }
324 }
325
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
334 struct 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
345 class wxInteractiveMoveHandler : public wxEvtHandler
346 {
347 public:
348 wxInteractiveMoveHandler(wxInteractiveMoveData& data) : m_data(data) {}
349
350 private:
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
360 BEGIN_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)
365 END_EVENT_TABLE()
366
367
368 static inline LINKAGEMODE
369 void 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
416 void 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
438 void 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
447 void 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
499 void wxInteractiveMoveHandler::OnMouseUp(wxMouseEvent& event)
500 {
501 m_data.m_evtLoop->Exit();
502 }
503
504
505 void 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
542 // ----------------------------------------------------------------------------
543 // actions
544 // ----------------------------------------------------------------------------
545
546 void 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;
573
574 default:
575 wxFAIL_MSG(wxT("incorrect button specification"));
576 }
577 }
578
579 bool wxTopLevelWindow::PerformAction(const wxControlAction& action,
580 long numArg,
581 const wxString& strArg)
582 {
583 bool isActive = numArg != 0;
584
585 if ( action == wxACTION_TOPLEVEL_ACTIVATE )
586 {
587 if ( m_isActive != isActive )
588 {
589 m_isActive = isActive;
590 RefreshTitleBar();
591 }
592 return TRUE;
593 }
594
595 else if ( action == wxACTION_TOPLEVEL_BUTTON_PRESS )
596 {
597 m_pressedButton = numArg;
598 RefreshTitleBar();
599 return TRUE;
600 }
601
602 else if ( action == wxACTION_TOPLEVEL_BUTTON_RELEASE )
603 {
604 m_pressedButton = 0;
605 RefreshTitleBar();
606 return TRUE;
607 }
608
609 else if ( action == wxACTION_TOPLEVEL_BUTTON_CLICK )
610 {
611 m_pressedButton = 0;
612 RefreshTitleBar();
613 ClickTitleBarButton(numArg);
614 return TRUE;
615 }
616
617 else if ( action == wxACTION_TOPLEVEL_MOVE )
618 {
619 InteractiveMove(wxINTERACTIVE_MOVE);
620 return TRUE;
621 }
622
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 }
637
638 else
639 return FALSE;
640 }
641
642
643 // ============================================================================
644 // wxStdFrameInputHandler: handles focus, resizing and titlebar buttons clicks
645 // ============================================================================
646
647 wxStdFrameInputHandler::wxStdFrameInputHandler(wxInputHandler *inphand)
648 : wxStdInputHandler(inphand)
649 {
650 m_winCapture = NULL;
651 m_winHitTest = 0;
652 m_winPressed = 0;
653 m_borderCursorOn = FALSE;
654 }
655
656 bool wxStdFrameInputHandler::HandleMouse(wxInputConsumer *consumer,
657 const wxMouseEvent& event)
658 {
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());
673
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 }
683 else if ( hit & wxHT_TOPLEVEL_TITLEBAR )
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 }
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
714 return wxStdInputHandler::HandleMouse(consumer, event);
715 }
716
717 bool wxStdFrameInputHandler::HandleMouseMove(wxInputConsumer *consumer,
718 const wxMouseEvent& event)
719 {
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);
730
731 m_winHitTest = hit;
732 return TRUE;
733 }
734 }
735 else if ( consumer->GetInputWindow()->GetWindowStyle() & wxRESIZE_BORDER )
736 {
737 wxTopLevelWindow *win = wxStaticCast(consumer->GetInputWindow(),
738 wxTopLevelWindow);
739 long hit = win->HitTest(event.GetPosition());
740
741 if ( hit != m_winHitTest )
742 {
743 m_winHitTest = hit;
744
745 if ( m_borderCursorOn )
746 {
747 m_borderCursorOn = FALSE;
748 win->SetCursor(m_origCursor);
749 }
750
751 if ( hit & wxHT_TOPLEVEL_ANY_BORDER )
752 {
753 m_borderCursorOn = TRUE;
754 wxCursor cur;
755
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 }
786
787 return wxStdInputHandler::HandleMouseMove(consumer, event);
788 }
789
790 bool wxStdFrameInputHandler::HandleActivation(wxInputConsumer *consumer,
791 bool activated)
792 {
793 if ( m_borderCursorOn )
794 {
795 consumer->GetInputWindow()->SetCursor(m_origCursor);
796 m_borderCursorOn = FALSE;
797 }
798 consumer->PerformAction(wxACTION_TOPLEVEL_ACTIVATE, activated);
799 return FALSE;
800 }