Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: downloads/OgreMain/src/OgreWindowEventUtilities.cpp @ 1

Last change on this file since 1 was 1, checked in by landauf, 17 years ago
File size: 9.7 KB
RevLine 
[1]1/*
2-----------------------------------------------------------------------------
3This source file is part of OGRE
4    (Object-oriented Graphics Rendering Engine)
5For the latest info, see http://www.ogre3d.org/
6
7Copyright (c) 2000-2006 Torus Knot Software Ltd
8Also see acknowledgements in Readme.html
9
10This program is free software; you can redistribute it and/or modify it under
11the terms of the GNU Lesser General Public License as published by the Free Software
12Foundation; either version 2 of the License, or (at your option) any later
13version.
14
15This program is distributed in the hope that it will be useful, but WITHOUT
16ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
17FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
18
19You should have received a copy of the GNU Lesser General Public License along with
20this program; if not, write to the Free Software Foundation, Inc., 59 Temple
21Place - Suite 330, Boston, MA 02111-1307, USA, or go to
22http://www.gnu.org/copyleft/lesser.txt.
23
24You may alternatively use this source under the terms of a specific version of
25the OGRE Unrestricted License provided you have obtained such a license from
26Torus Knot Software Ltd.
27-----------------------------------------------------------------------------
28*/
29#include "OgreStableHeaders.h"
30#include "OgreWindowEventUtilities.h"
31#include "OgreRenderWindow.h"
32#include "OgreLogManager.h"
33#include "OgreRoot.h"
34#include "OgreException.h"
35
36#if OGRE_PLATFORM == OGRE_PLATFORM_LINUX
37#include <X11/Xlib.h>
38void GLXProc( const XEvent &event );
39#endif
40
41using namespace Ogre;
42
43WindowEventUtilities::WindowEventListeners WindowEventUtilities::_msListeners;
44WindowEventUtilities::Windows WindowEventUtilities::_msWindows;
45
46//--------------------------------------------------------------------------------//
47void WindowEventUtilities::messagePump()
48{
49#if OGRE_PLATFORM == OGRE_PLATFORM_WIN32
50        // Windows Message Loop (NULL means check all HWNDs belonging to this context)
51        MSG  msg;
52        while( PeekMessage( &msg, NULL, 0U, 0U, PM_REMOVE ) )
53        {
54                TranslateMessage( &msg );
55                DispatchMessage( &msg );
56        }
57#elif OGRE_PLATFORM == OGRE_PLATFORM_LINUX
58        //GLX Message Pump (Display is probably Common for all RenderWindows.. But, to be safe loop
59        //through all)
60        Windows::iterator i = _msWindows.begin(), e = _msWindows.end();
61        for( ; i != e; ++i )
62        {
63                ::Display* display;
64                (*i)->getCustomAttribute("DISPLAY", &display);
65                while(XPending(display) > 0)
66                {
67                        XEvent event;
68                        XNextEvent(display, &event);
69                        GLXProc(event);
70                }
71        }
72        #elif OGRE_PLATFORM == OGRE_PLATFORM_APPLE
73        // OSX Message Pump
74        EventRef event = NULL;
75        EventTargetRef targetWindow;
76        targetWindow = GetEventDispatcherTarget();
77        if( ReceiveNextEvent( 0, NULL, kEventDurationNoWait, true, &event ) == noErr )
78        {
79                SendEventToEventTarget( event, targetWindow );
80                ReleaseEvent( event );
81        }
82#endif
83}
84
85//--------------------------------------------------------------------------------//
86void WindowEventUtilities::addWindowEventListener( RenderWindow* window, WindowEventListener* listener )
87{
88        _msListeners.insert(std::make_pair(window, listener));
89}
90
91//--------------------------------------------------------------------------------//
92void WindowEventUtilities::removeWindowEventListener( RenderWindow* window, WindowEventListener* listener )
93{
94        WindowEventListeners::iterator i = _msListeners.begin(), e = _msListeners.end();
95
96        for( ; i != e; ++i )
97        {
98                if( i->first == window && i->second == listener )
99                {
100                        _msListeners.erase(i);
101                        break;
102                }
103        }
104}
105
106//--------------------------------------------------------------------------------//
107void WindowEventUtilities::_addRenderWindow(RenderWindow* window)
108{
109        _msWindows.push_back(window);
110}
111
112//--------------------------------------------------------------------------------//
113void WindowEventUtilities::_removeRenderWindow(RenderWindow* window)
114{
115        Windows::iterator i = std::find(_msWindows.begin(), _msWindows.end(), window);
116        if( i != _msWindows.end() )
117                _msWindows.erase( i );
118}
119
120#if OGRE_PLATFORM == OGRE_PLATFORM_WIN32
121//--------------------------------------------------------------------------------//
122LRESULT CALLBACK WindowEventUtilities::_WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
123{
124        if (uMsg == WM_CREATE)
125        {       // Store pointer to Win32Window in user data area
126                SetWindowLongPtr(hWnd, GWLP_USERDATA, (LONG)(((LPCREATESTRUCT)lParam)->lpCreateParams));
127                return 0;
128        }
129
130        // look up window instance
131        // note: it is possible to get a WM_SIZE before WM_CREATE
132        RenderWindow* win = (RenderWindow*)GetWindowLongPtr(hWnd, GWLP_USERDATA);
133        if (!win)
134                return DefWindowProc(hWnd, uMsg, wParam, lParam);
135
136        //LogManager* log = LogManager::getSingletonPtr();
137        //Iterator of all listeners registered to this RenderWindow
138        WindowEventListeners::iterator start = _msListeners.lower_bound(win),
139                                                end = _msListeners.upper_bound(win);
140
141        switch( uMsg )
142        {
143        case WM_ACTIVATE:
144        {
145                bool active = (LOWORD(wParam) != WA_INACTIVE);
146                win->setActive( active );
147                for( ; start != end; ++start )
148                        (start->second)->windowFocusChange(win);
149                break;
150        }
151        case WM_SYSKEYDOWN:
152                switch( wParam )
153                {
154                case VK_CONTROL:
155                case VK_SHIFT:
156                case VK_MENU: //ALT
157                        //return zero to bypass defProc and signal we processed the message
158                        return 0;
159                }
160                break;
161        case WM_SYSKEYUP:
162                switch( wParam )
163                {
164                case VK_CONTROL:
165                case VK_SHIFT:
166                case VK_MENU: //ALT
167                case VK_F10:
168                        //return zero to bypass defProc and signal we processed the message
169                        return 0;
170                }
171                break;
172        case WM_SYSCHAR:
173                // return zero to bypass defProc and signal we processed the message, unless it's an ALT-space
174                if (wParam != VK_SPACE)
175                        return 0;
176                break;
177        case WM_ENTERSIZEMOVE:
178                //log->logMessage("WM_ENTERSIZEMOVE");
179                break;
180        case WM_EXITSIZEMOVE:
181                //log->logMessage("WM_EXITSIZEMOVE");
182                break;
183        case WM_MOVE:
184                //log->logMessage("WM_MOVE");
185                win->windowMovedOrResized();
186                for( ; start != end; ++start )
187                        (start->second)->windowMoved(win);
188                break;
189        case WM_DISPLAYCHANGE:
190                win->windowMovedOrResized();
191                for( ; start != end; ++start )
192                        (start->second)->windowResized(win);
193                break;
194        case WM_SIZE:
195                //log->logMessage("WM_SIZE");
196                win->windowMovedOrResized();
197                for( ; start != end; ++start )
198                        (start->second)->windowResized(win);
199                break;
200        case WM_GETMINMAXINFO:
201                // Prevent the window from going smaller than some minimu size
202                ((MINMAXINFO*)lParam)->ptMinTrackSize.x = 100;
203                ((MINMAXINFO*)lParam)->ptMinTrackSize.y = 100;
204                break;
205        case WM_CLOSE:
206                //log->logMessage("WM_CLOSE");
207                win->destroy();
208                for( ; start != end; ++start )
209                        (start->second)->windowClosed(win);
210                return 0;
211        }
212
213        return DefWindowProc( hWnd, uMsg, wParam, lParam );
214}
215#elif OGRE_PLATFORM == OGRE_PLATFORM_LINUX
216//--------------------------------------------------------------------------------//
217void GLXProc( const XEvent &event )
218{
219        //We have to find appropriate window based on window id ( kindof hackish :/,
220        //but at least this only happens when there is a Window's event - and not that often
221        WindowEventUtilities::Windows::iterator i = WindowEventUtilities::_msWindows.begin(),
222                                                e = WindowEventUtilities::_msWindows.end();
223        RenderWindow* win = 0;
224        for(; i != e; ++i )
225        {
226                std::size_t wind = 0;
227                (*i)->getCustomAttribute("WINDOW", &wind);
228                if( event.xany.window == wind )
229                {
230                        win = *i;
231                        break;
232                }
233        }
234
235        //Sometimes, seems we get other windows, so just ignore
236        if( win == 0 ) return;
237
238        //Now that we have the correct RenderWindow for the generated Event, get an iterator for the listeners
239        WindowEventUtilities::WindowEventListeners::iterator
240                start = WindowEventUtilities::_msListeners.lower_bound(win),
241                end   = WindowEventUtilities::_msListeners.upper_bound(win);
242
243        switch(event.type)
244        {
245        case ClientMessage:
246        {
247                ::Atom atom;
248                win->getCustomAttribute("ATOM", &atom);
249                if(event.xclient.format == 32 && event.xclient.data.l[0] == (long)atom)
250                {       //Window Closed (via X button)
251                        //Send message first, to allow app chance to unregister things that need done before
252                        //window is shutdown
253                        for( ; start != end; ++start )
254                                (start->second)->windowClosed(win);
255                        win->destroy();
256                }
257                break;
258        }
259        case ConfigureNotify:   //Moving or Resizing
260                unsigned int width, height, depth;
261                int left, top;
262                win->getMetrics(width, height, depth, left, top);
263
264                //determine if moving or sizing:
265                if( left == event.xconfigure.x && top == event.xconfigure.y )
266                {       //Resize width, height
267                        win->windowMovedOrResized();
268                        for( ; start != end; ++start )
269                                (start->second)->windowResized(win);
270                }
271                else if( width == event.xconfigure.width && height == event.xconfigure.height )
272                {       //Moving x, y
273                        win->windowMovedOrResized();
274                        for( ; start != end; ++start )
275                                (start->second)->windowMoved(win);
276                }
277                break;
278        case MapNotify:   //Restored
279                win->setActive( true );
280                for( ; start != end; ++start )
281                        (start->second)->windowFocusChange(win);
282                break;
283        case UnmapNotify: //Minimised
284                win->setActive( false );
285                win->setVisible( false );
286                for( ; start != end; ++start )
287                        (start->second)->windowFocusChange(win);
288                break;
289        case VisibilityNotify:
290                switch(event.xvisibility.state)
291                {
292                case VisibilityUnobscured:
293                        win->setActive( true );
294                        win->setVisible( true );
295                        break;
296                case VisibilityPartiallyObscured:
297                        win->setActive( true );
298                        win->setVisible( true );
299                        break;
300                case VisibilityFullyObscured:
301                        win->setActive( false );
302                        win->setVisible( false );
303                        break;
304                }
305
306                //Notify Listeners that focus of window has changed in some way
307                for( ; start != end; ++start )
308                        (start->second)->windowFocusChange(win);
309                break;
310        default:
311                break;
312        } //End switch event.type
313}
314#endif
Note: See TracBrowser for help on using the repository browser.