1/*
2    SDL - Simple DirectMedia Layer
3    Copyright (C) 1997-2006 Sam Lantinga
4
5    This library is free software; you can redistribute it and/or
6    modify it under the terms of the GNU Lesser General Public
7    License as published by the Free Software Foundation; either
8    version 2.1 of the License, or (at your option) any later version.
9
10    This library is distributed in the hope that it will be useful,
11    but WITHOUT ANY WARRANTY; without even the implied warranty of
12    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13    Lesser General Public License for more details.
14
15    You should have received a copy of the GNU Lesser General Public
16    License along with this library; if not, write to the Free Software
17    Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
18
19    Sam Lantinga
20    slouken@libsdl.org
21*/
22
23#ifndef _SDL_BWin_h
24#define _SDL_BWin_h
25
26#include "SDL_config.h"
27
28#include <stdio.h>
29#include <AppKit.h>
30#include <InterfaceKit.h>
31#include <be/game/DirectWindow.h>
32#if SDL_VIDEO_OPENGL
33#include <be/opengl/GLView.h>
34#endif
35#include <support/UTF8.h>
36
37#include "../../main/beos/SDL_BeApp.h"
38#include "SDL_events.h"
39#include "SDL_BView.h"
40
41extern "C" {
42#include "../../events/SDL_events_c.h"
43
44extern int mouse_relative;
45};
46
47class SDL_BWin : public BDirectWindow
48{
49public:
50	SDL_BWin(BRect bounds) :
51			BDirectWindow(bounds, "Untitled", B_TITLED_WINDOW, 0) {
52		last_buttons = 0;
53		the_view = NULL;
54#if SDL_VIDEO_OPENGL
55		SDL_GLView = NULL;
56#endif
57		SDL_View = NULL;
58		Unlock();
59		shown = false;
60		inhibit_resize = false;
61	}
62
63	virtual ~SDL_BWin() {
64		Lock();
65		if ( the_view ) {
66#if SDL_VIDEO_OPENGL
67			if ( the_view == SDL_GLView ) {
68				SDL_GLView->UnlockGL();
69			}
70#endif
71			RemoveChild(the_view);
72			the_view = NULL;
73		}
74		Unlock();
75#if SDL_VIDEO_OPENGL
76		if ( SDL_GLView ) {
77			delete SDL_GLView;
78		}
79#endif
80		if ( SDL_View ) {
81			delete SDL_View;
82		}
83	}
84
85
86	/* Override the Show() method so we can tell when we've been shown */
87	virtual void Show(void) {
88		BWindow::Show();
89		shown = true;
90	}
91	virtual bool Shown(void) {
92		return (shown);
93	}
94	/* If called, the next resize event will not be forwarded to SDL. */
95	virtual void InhibitResize(void) {
96		inhibit_resize=true;
97	}
98	/* Handle resizing of the window */
99	virtual void FrameResized(float width, float height) {
100		if(inhibit_resize)
101			inhibit_resize = false;
102		else
103			SDL_PrivateResize((int)width, (int)height);
104	}
105	virtual int CreateView(Uint32 flags, Uint32 gl_flags) {
106		int retval;
107
108		retval = 0;
109		Lock();
110		if ( flags & SDL_OPENGL ) {
111#if SDL_VIDEO_OPENGL
112			if ( SDL_GLView == NULL ) {
113				SDL_GLView = new BGLView(Bounds(), "SDL GLView",
114					 	B_FOLLOW_ALL_SIDES, (B_WILL_DRAW|B_FRAME_EVENTS),
115					 	gl_flags);
116				SDL_GLView->EnableDirectMode(true);
117			}
118			if ( the_view != SDL_GLView ) {
119				if ( the_view ) {
120					RemoveChild(the_view);
121				}
122				AddChild(SDL_GLView);
123				SDL_GLView->LockGL();
124				the_view = SDL_GLView;
125			}
126#else
127			SDL_SetError("OpenGL support not enabled");
128			retval = -1;
129#endif
130		} else {
131			if ( SDL_View == NULL ) {
132				SDL_View = new SDL_BView(Bounds());
133			}
134			if ( the_view != SDL_View ) {
135				if ( the_view ) {
136#if SDL_VIDEO_OPENGL
137					if ( the_view == SDL_GLView ) {
138						SDL_GLView->UnlockGL();
139					}
140#endif
141					RemoveChild(the_view);
142				}
143				AddChild(SDL_View);
144				the_view = SDL_View;
145			}
146		}
147		Unlock();
148		return(retval);
149	}
150	virtual void SetBitmap(BBitmap *bitmap) {
151		SDL_View->SetBitmap(bitmap);
152	}
153	virtual void SetXYOffset(int x, int y) {
154#if SDL_VIDEO_OPENGL
155		if ( the_view == SDL_GLView ) {
156			return;
157		}
158#endif
159		SDL_View->SetXYOffset(x, y);
160	}
161	virtual void GetXYOffset(int &x, int &y) {
162#if SDL_VIDEO_OPENGL
163		if ( the_view == SDL_GLView ) {
164			x = 0;
165			y = 0;
166			return;
167		}
168#endif
169		SDL_View->GetXYOffset(x, y);
170	}
171	virtual void GetXYOffset(float &x, float &y) {
172#if SDL_VIDEO_OPENGL
173		if ( the_view == SDL_GLView ) {
174			x = 0.0f;
175			y = 0.0f;
176			return;
177		}
178#endif
179		SDL_View->GetXYOffset(x, y);
180	}
181	virtual bool BeginDraw(void) {
182		return(Lock());
183	}
184	virtual void DrawAsync(BRect updateRect) {
185		SDL_View->DrawAsync(updateRect);
186	}
187	virtual void EndDraw(void) {
188		SDL_View->Sync();
189		Unlock();
190	}
191#if SDL_VIDEO_OPENGL
192	virtual void SwapBuffers(void) {
193		SDL_GLView->UnlockGL();
194		SDL_GLView->LockGL();
195		SDL_GLView->SwapBuffers();
196	}
197#endif
198	virtual BView *View(void) {
199		return(the_view);
200	}
201
202	/* Hook functions -- overridden */
203	virtual void Minimize(bool minimize) {
204		/* This is only called when mimimized, not when restored */
205		//SDL_PrivateAppActive(minimize, SDL_APPACTIVE);
206		BWindow::Minimize(minimize);
207	}
208	virtual void WindowActivated(bool active) {
209		SDL_PrivateAppActive(active, SDL_APPINPUTFOCUS);
210	}
211	virtual bool QuitRequested(void) {
212		if ( SDL_BeAppActive > 0 ) {
213			SDL_PrivateQuit();
214			/* We don't ever actually close the window here because
215			   the application should respond to the quit request,
216			   or ignore it as desired.
217			 */
218			return(false);
219		}
220		return(true);	/* Close the app window */
221	}
222	virtual void Quit() {
223		if (!IsLocked())
224			Lock();
225		BDirectWindow::Quit();
226	}
227
228	virtual int16 Translate2Unicode(const char *buf) {
229		int32 state, srclen, dstlen;
230		unsigned char destbuf[2];
231		Uint16 unicode = 0;
232
233		if ((uchar)buf[0] > 127) {
234			state = 0;
235			srclen = SDL_strlen(buf);
236			dstlen = sizeof(destbuf);
237			convert_from_utf8(B_UNICODE_CONVERSION, buf, &srclen, (char *)destbuf, &dstlen, &state);
238			unicode = destbuf[0];
239			unicode <<= 8;
240			unicode |= destbuf[1];
241		} else
242			unicode = buf[0];
243
244		/* For some reason function keys map to control characters */
245# define CTRL(X)	((X)-'@')
246		switch (unicode) {
247		    case CTRL('A'):
248		    case CTRL('B'):
249		    case CTRL('C'):
250		    case CTRL('D'):
251		    case CTRL('E'):
252		    case CTRL('K'):
253		    case CTRL('L'):
254		    case CTRL('P'):
255			if ( ! (SDL_GetModState() & KMOD_CTRL) )
256				unicode = 0;
257			break;
258			/* Keyboard input maps newline to carriage return */
259			case '\n':
260				unicode = '\r';
261			break;
262		    default:
263			break;
264		}
265
266		return unicode;
267	}
268
269	virtual void DispatchMessage(BMessage *msg, BHandler *target);
270
271private:
272#if SDL_VIDEO_OPENGL
273	BGLView *SDL_GLView;
274#endif
275	SDL_BView *SDL_View;
276	BView *the_view;
277	bool shown;
278	bool inhibit_resize;
279	int32 last_buttons;
280};
281
282#endif /* _SDL_BWin_h */
283