1/*
2    SDL - Simple DirectMedia Layer
3    Copyright (C) 1997-2012 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 "SDL_opengl.h"
34#include <be/opengl/GLView.h>
35#endif
36#include <support/UTF8.h>
37
38#include "../../main/beos/SDL_BeApp.h"
39#include "SDL_events.h"
40#include "SDL_BView.h"
41
42extern "C" {
43#include "../../events/SDL_events_c.h"
44
45extern int mouse_relative;
46};
47
48class SDL_BWin : public BDirectWindow
49{
50public:
51	SDL_BWin(BRect bounds) :
52			BDirectWindow(bounds, "Untitled", B_TITLED_WINDOW, 0) {
53		last_buttons = 0;
54		the_view = NULL;
55#if SDL_VIDEO_OPENGL
56		SDL_GLView = NULL;
57#endif
58		SDL_View = NULL;
59		Unlock();
60		shown = false;
61		inhibit_resize = false;
62	}
63
64	virtual ~SDL_BWin() {
65		Lock();
66		if ( the_view ) {
67#if SDL_VIDEO_OPENGL
68			if ( the_view == SDL_GLView ) {
69				SDL_GLView->UnlockGL();
70			}
71#endif
72			RemoveChild(the_view);
73			the_view = NULL;
74		}
75		Unlock();
76#if SDL_VIDEO_OPENGL
77		if ( SDL_GLView ) {
78			delete SDL_GLView;
79		}
80#endif
81		if ( SDL_View ) {
82			delete SDL_View;
83		}
84	}
85
86
87	/* Override the Show() method so we can tell when we've been shown */
88	virtual void Show(void) {
89		BWindow::Show();
90		shown = true;
91	}
92	virtual bool Shown(void) {
93		return (shown);
94	}
95	/* If called, the next resize event will not be forwarded to SDL. */
96	virtual void InhibitResize(void) {
97		inhibit_resize=true;
98	}
99	/* Handle resizing of the window */
100	virtual void FrameResized(float width, float height) {
101		if(inhibit_resize)
102			inhibit_resize = false;
103		else
104			SDL_PrivateResize((int)width, (int)height);
105	}
106	virtual int CreateView(Uint32 flags, Uint32 gl_flags) {
107		int retval;
108
109		retval = 0;
110		Lock();
111		if ( flags & SDL_OPENGL ) {
112#if SDL_VIDEO_OPENGL
113			if ( SDL_GLView == NULL ) {
114				SDL_GLView = new BGLView(Bounds(), "SDL GLView",
115					 	B_FOLLOW_ALL_SIDES, (B_WILL_DRAW|B_FRAME_EVENTS),
116					 	gl_flags|BGL_DOUBLE);
117				SDL_GLView->EnableDirectMode(true);
118			}
119			if ( the_view != SDL_GLView ) {
120				if ( the_view ) {
121					RemoveChild(the_view);
122				}
123				AddChild(SDL_GLView);
124				SDL_GLView->LockGL();
125				the_view = SDL_GLView;
126			}
127#else
128			SDL_SetError("OpenGL support not enabled");
129			retval = -1;
130#endif
131		} else {
132			if ( SDL_View == NULL ) {
133				SDL_View = new SDL_BView(Bounds());
134			}
135			if ( the_view != SDL_View ) {
136				if ( the_view ) {
137					RemoveChild(the_view);
138				}
139				AddChild(SDL_View);
140				the_view = SDL_View;
141			}
142		}
143#if SDL_VIDEO_OPENGL
144		if ( the_view == SDL_GLView ) {
145			SDL_GLView->UnlockGL();
146		}
147#endif
148		Unlock();
149		return(retval);
150	}
151	virtual void SetBitmap(BBitmap *bitmap) {
152		SDL_View->SetBitmap(bitmap);
153	}
154	virtual void SetXYOffset(int x, int y) {
155#if SDL_VIDEO_OPENGL
156		if ( the_view == SDL_GLView ) {
157			return;
158		}
159#endif
160		SDL_View->SetXYOffset(x, y);
161	}
162	virtual void GetXYOffset(int &x, int &y) {
163#if SDL_VIDEO_OPENGL
164		if ( the_view == SDL_GLView ) {
165			x = 0;
166			y = 0;
167			return;
168		}
169#endif
170		SDL_View->GetXYOffset(x, y);
171	}
172	virtual void GetXYOffset(float &x, float &y) {
173#if SDL_VIDEO_OPENGL
174		if ( the_view == SDL_GLView ) {
175			x = 0.0f;
176			y = 0.0f;
177			return;
178		}
179#endif
180		SDL_View->GetXYOffset(x, y);
181	}
182	virtual bool BeginDraw(void) {
183		return(Lock());
184	}
185	virtual void DrawAsync(BRect updateRect) {
186		SDL_View->DrawAsync(updateRect);
187	}
188	virtual void EndDraw(void) {
189		SDL_View->Sync();
190		Unlock();
191	}
192#if SDL_VIDEO_OPENGL
193	virtual void SwapBuffers(void) {
194		SDL_GLView->UnlockGL();
195		SDL_GLView->SwapBuffers();
196		SDL_GLView->LockGL();
197	}
198#endif
199	virtual BView *View(void) {
200		return(the_view);
201	}
202
203	/* Hook functions -- overridden */
204	virtual void Minimize(bool minimize) {
205		/* This is only called when mimimized, not when restored */
206		//SDL_PrivateAppActive(minimize, SDL_APPACTIVE);
207		BWindow::Minimize(minimize);
208	}
209	virtual void WindowActivated(bool active) {
210		SDL_PrivateAppActive(active, SDL_APPINPUTFOCUS);
211	}
212	virtual bool QuitRequested(void) {
213		if ( SDL_BeAppActive > 0 ) {
214			SDL_PrivateQuit();
215			/* We don't ever actually close the window here because
216			   the application should respond to the quit request,
217			   or ignore it as desired.
218			 */
219#if SDL_VIDEO_OPENGL
220			if ( SDL_GLView != NULL ) {
221				SDL_GLView->EnableDirectMode(false);
222			}
223#endif
224			return(false);
225		}
226		return(true);	/* Close the app window */
227	}
228	virtual void Quit() {
229		if (!IsLocked())
230			Lock();
231		BDirectWindow::Quit();
232	}
233
234	virtual int16 Translate2Unicode(const char *buf) {
235		int32 state, srclen, dstlen;
236		unsigned char destbuf[2];
237		Uint16 unicode = 0;
238
239		if ((uchar)buf[0] > 127) {
240			state = 0;
241			srclen = SDL_strlen(buf);
242			dstlen = sizeof(destbuf);
243			convert_from_utf8(B_UNICODE_CONVERSION, buf, &srclen, (char *)destbuf, &dstlen, &state);
244			unicode = destbuf[0];
245			unicode <<= 8;
246			unicode |= destbuf[1];
247		} else
248			unicode = buf[0];
249
250		/* For some reason function keys map to control characters */
251# define CTRL(X)	((X)-'@')
252		switch (unicode) {
253		    case CTRL('A'):
254		    case CTRL('B'):
255		    case CTRL('C'):
256		    case CTRL('D'):
257		    case CTRL('E'):
258		    case CTRL('K'):
259		    case CTRL('L'):
260		    case CTRL('P'):
261			if ( ! (SDL_GetModState() & KMOD_CTRL) )
262				unicode = 0;
263			break;
264			/* Keyboard input maps newline to carriage return */
265			case '\n':
266				unicode = '\r';
267			break;
268		    default:
269			break;
270		}
271
272		return unicode;
273	}
274
275	virtual void DispatchMessage(BMessage *msg, BHandler *target);
276
277	virtual void DirectConnected(direct_buffer_info *info);
278
279private:
280#if SDL_VIDEO_OPENGL
281	BGLView *SDL_GLView;
282#endif
283	SDL_BView *SDL_View;
284	BView *the_view;
285	bool shown;
286	bool inhibit_resize;
287	int32 last_buttons;
288};
289
290#endif /* _SDL_BWin_h */
291