Atlas - SDL_BWin.h

Home / ext / SDL2 / src / video / haiku Lines: 1 | Size: 20454 bytes [Download] [Show on GitHub] [Search similar files] [Raw] [Raw (proxy)]
[FILE BEGIN]
1/* 2 Simple DirectMedia Layer 3 Copyright (C) 1997-2018 Sam Lantinga <[email protected]> 4 5 This software is provided 'as-is', without any express or implied 6 warranty. In no event will the authors be held liable for any damages 7 arising from the use of this software. 8 9 Permission is granted to anyone to use this software for any purpose, 10 including commercial applications, and to alter it and redistribute it 11 freely, subject to the following restrictions: 12 13 1. The origin of this software must not be misrepresented; you must not 14 claim that you wrote the original software. If you use this software 15 in a product, an acknowledgment in the product documentation would be 16 appreciated but is not required. 17 2. Altered source versions must be plainly marked as such, and must not be 18 misrepresented as being the original software. 19 3. This notice may not be removed or altered from any source distribution. 20*/ 21 22#ifndef SDL_BWin_h_ 23#define SDL_BWin_h_ 24 25#ifdef __cplusplus 26extern "C" { 27#endif 28 29#include "../../SDL_internal.h" 30#include "SDL.h" 31#include "SDL_syswm.h" 32#include "SDL_bframebuffer.h" 33 34#ifdef __cplusplus 35} 36#endif 37 38#include <stdio.h> 39#include <AppKit.h> 40#include <InterfaceKit.h> 41#include <game/DirectWindow.h> 42#if SDL_VIDEO_OPENGL 43#include <opengl/GLView.h> 44#endif 45#include "SDL_events.h" 46#include "../../main/haiku/SDL_BApp.h" 47 48 49enum WinCommands { 50 BWIN_MOVE_WINDOW, 51 BWIN_RESIZE_WINDOW, 52 BWIN_SHOW_WINDOW, 53 BWIN_HIDE_WINDOW, 54 BWIN_MAXIMIZE_WINDOW, 55 BWIN_MINIMIZE_WINDOW, 56 BWIN_RESTORE_WINDOW, 57 BWIN_SET_TITLE, 58 BWIN_SET_BORDERED, 59 BWIN_SET_RESIZABLE, 60 BWIN_FULLSCREEN 61}; 62 63 64class SDL_BWin:public BDirectWindow 65{ 66 public: 67 /* Constructor/Destructor */ 68 SDL_BWin(BRect bounds, window_look look, uint32 flags) 69 : BDirectWindow(bounds, "Untitled", look, B_NORMAL_WINDOW_FEEL, flags) 70 { 71 _last_buttons = 0; 72 73#if SDL_VIDEO_OPENGL 74 _SDL_GLView = NULL; 75 _gl_type = 0; 76#endif 77 _shown = false; 78 _inhibit_resize = false; 79 _mouse_focused = false; 80 _prev_frame = NULL; 81 82 /* Handle framebuffer stuff */ 83 _connected = _connection_disabled = false; 84 _buffer_created = _buffer_dirty = false; 85 _trash_window_buffer = false; 86 _buffer_locker = new BLocker(); 87 _bitmap = NULL; 88 _clips = NULL; 89 90#ifdef DRAWTHREAD 91 _draw_thread_id = spawn_thread(HAIKU_DrawThread, "drawing_thread", 92 B_NORMAL_PRIORITY, (void*) this); 93 resume_thread(_draw_thread_id); 94#endif 95 } 96 97 virtual ~ SDL_BWin() 98 { 99 Lock(); 100 _connection_disabled = true; 101 int32 result; 102 103#if SDL_VIDEO_OPENGL 104 if (_SDL_GLView) { 105 _SDL_GLView->UnlockGL(); 106 RemoveChild(_SDL_GLView); /* Why was this outside the if 107 statement before? */ 108 } 109 110#endif 111 Unlock(); 112#if SDL_VIDEO_OPENGL 113 if (_SDL_GLView) { 114 delete _SDL_GLView; 115 } 116#endif 117 118 delete _prev_frame; 119 120 /* Clean up framebuffer stuff */ 121 _buffer_locker->Lock(); 122#ifdef DRAWTHREAD 123 wait_for_thread(_draw_thread_id, &result); 124#endif 125 free(_clips); 126 delete _buffer_locker; 127 } 128 129 130 /* * * * * OpenGL functionality * * * * */ 131#if SDL_VIDEO_OPENGL 132 virtual BGLView *CreateGLView(Uint32 gl_flags) { 133 Lock(); 134 if (_SDL_GLView == NULL) { 135 _SDL_GLView = new BGLView(Bounds(), "SDL GLView", 136 B_FOLLOW_ALL_SIDES, 137 (B_WILL_DRAW | B_FRAME_EVENTS), 138 gl_flags); 139 _gl_type = gl_flags; 140 } 141 AddChild(_SDL_GLView); 142 _SDL_GLView->EnableDirectMode(true); 143 _SDL_GLView->LockGL(); /* "New" GLViews are created */ 144 Unlock(); 145 return (_SDL_GLView); 146 } 147 148 virtual void RemoveGLView() { 149 Lock(); 150 if(_SDL_GLView) { 151 _SDL_GLView->UnlockGL(); 152 RemoveChild(_SDL_GLView); 153 } 154 Unlock(); 155 } 156 157 virtual void SwapBuffers(void) { 158 _SDL_GLView->UnlockGL(); 159 _SDL_GLView->LockGL(); 160 _SDL_GLView->SwapBuffers(); 161 } 162#endif 163 164 /* * * * * Framebuffering* * * * */ 165 virtual void DirectConnected(direct_buffer_info *info) { 166 if(!_connected && _connection_disabled) { 167 return; 168 } 169 170 /* Determine if the pixel buffer is usable after this update */ 171 _trash_window_buffer = _trash_window_buffer 172 || ((info->buffer_state & B_BUFFER_RESIZED) 173 || (info->buffer_state & B_BUFFER_RESET) 174 || (info->driver_state == B_MODE_CHANGED)); 175 LockBuffer(); 176 177 switch(info->buffer_state & B_DIRECT_MODE_MASK) { 178 case B_DIRECT_START: 179 _connected = true; 180 181 case B_DIRECT_MODIFY: 182 if(_clips) { 183 free(_clips); 184 _clips = NULL; 185 } 186 187 _num_clips = info->clip_list_count; 188 _clips = (clipping_rect *)malloc(_num_clips*sizeof(clipping_rect)); 189 if(_clips) { 190 memcpy(_clips, info->clip_list, 191 _num_clips*sizeof(clipping_rect)); 192 193 _bits = (uint8*) info->bits; 194 _row_bytes = info->bytes_per_row; 195 _bounds = info->window_bounds; 196 _bytes_per_px = info->bits_per_pixel / 8; 197 _buffer_dirty = true; 198 } 199 break; 200 201 case B_DIRECT_STOP: 202 _connected = false; 203 break; 204 } 205#if SDL_VIDEO_OPENGL 206 if(_SDL_GLView) { 207 _SDL_GLView->DirectConnected(info); 208 } 209#endif 210 211 212 /* Call the base object directconnected */ 213 BDirectWindow::DirectConnected(info); 214 215 UnlockBuffer(); 216 217 } 218 219 220 221 222 /* * * * * Event sending * * * * */ 223 /* Hook functions */ 224 virtual void FrameMoved(BPoint origin) { 225 /* Post a message to the BApp so that it can handle the window event */ 226 BMessage msg(BAPP_WINDOW_MOVED); 227 msg.AddInt32("window-x", (int)origin.x); 228 msg.AddInt32("window-y", (int)origin.y); 229 _PostWindowEvent(msg); 230 231 /* Perform normal hook operations */ 232 BDirectWindow::FrameMoved(origin); 233 } 234 235 virtual void FrameResized(float width, float height) { 236 /* Post a message to the BApp so that it can handle the window event */ 237 BMessage msg(BAPP_WINDOW_RESIZED); 238 239 msg.AddInt32("window-w", (int)width + 1); 240 msg.AddInt32("window-h", (int)height + 1); 241 _PostWindowEvent(msg); 242 243 /* Perform normal hook operations */ 244 BDirectWindow::FrameResized(width, height); 245 } 246 247 virtual bool QuitRequested() { 248 BMessage msg(BAPP_WINDOW_CLOSE_REQUESTED); 249 _PostWindowEvent(msg); 250 251 /* We won't allow a quit unless asked by DestroyWindow() */ 252 return false; 253 } 254 255 virtual void WindowActivated(bool active) { 256 BMessage msg(BAPP_KEYBOARD_FOCUS); /* Mouse focus sold separately */ 257 msg.AddBool("focusGained", active); 258 _PostWindowEvent(msg); 259 } 260 261 virtual void Zoom(BPoint origin, 262 float width, 263 float height) { 264 BMessage msg(BAPP_MAXIMIZE); /* Closest thing to maximization Haiku has */ 265 _PostWindowEvent(msg); 266 267 /* Before the window zooms, record its size */ 268 if( !_prev_frame ) 269 _prev_frame = new BRect(Frame()); 270 271 /* Perform normal hook operations */ 272 BDirectWindow::Zoom(origin, width, height); 273 } 274 275 /* Member functions */ 276 virtual void Show() { 277 while(IsHidden()) { 278 BDirectWindow::Show(); 279 } 280 _shown = true; 281 282 BMessage msg(BAPP_SHOW); 283 _PostWindowEvent(msg); 284 } 285 286 virtual void Hide() { 287 BDirectWindow::Hide(); 288 _shown = false; 289 290 BMessage msg(BAPP_HIDE); 291 _PostWindowEvent(msg); 292 } 293 294 virtual void Minimize(bool minimize) { 295 BDirectWindow::Minimize(minimize); 296 int32 minState = (minimize ? BAPP_MINIMIZE : BAPP_RESTORE); 297 298 BMessage msg(minState); 299 _PostWindowEvent(msg); 300 } 301 302 303 /* BView message interruption */ 304 virtual void DispatchMessage(BMessage * msg, BHandler * target) 305 { 306 BPoint where; /* Used by mouse moved */ 307 int32 buttons; /* Used for mouse button events */ 308 int32 key; /* Used for key events */ 309 310 switch (msg->what) { 311 case B_MOUSE_MOVED: 312 int32 transit; 313 if (msg->FindPoint("where", &where) == B_OK 314 && msg->FindInt32("be:transit", &transit) == B_OK) { 315 _MouseMotionEvent(where, transit); 316 } 317 318 /* FIXME: Apparently a button press/release event might be dropped 319 if made before before a different button is released. Does 320 B_MOUSE_MOVED have the data needed to check if a mouse button 321 state has changed? */ 322 if (msg->FindInt32("buttons", &buttons) == B_OK) { 323 _MouseButtonEvent(buttons); 324 } 325 break; 326 327 case B_MOUSE_DOWN: 328 case B_MOUSE_UP: 329 /* _MouseButtonEvent() detects any and all buttons that may have 330 changed state, as well as that button's new state */ 331 if (msg->FindInt32("buttons", &buttons) == B_OK) { 332 _MouseButtonEvent(buttons); 333 } 334 break; 335 336 case B_MOUSE_WHEEL_CHANGED: 337 float x, y; 338 if (msg->FindFloat("be:wheel_delta_x", &x) == B_OK 339 && msg->FindFloat("be:wheel_delta_y", &y) == B_OK) { 340 _MouseWheelEvent((int)x, (int)y); 341 } 342 break; 343 344 case B_KEY_DOWN: 345 { 346 int32 i = 0; 347 int8 byte; 348 int8 bytes[4] = { 0, 0, 0, 0 }; 349 while (i < 4 && msg->FindInt8("byte", i, &byte) == B_OK) { 350 bytes[i] = byte; 351 i++; 352 } 353 if (msg->FindInt32("key", &key) == B_OK) { 354 _KeyEvent((SDL_Scancode)key, &bytes[0], i, SDL_PRESSED); 355 } 356 } 357 break; 358 359 case B_UNMAPPED_KEY_DOWN: /* modifier keys are unmapped */ 360 if (msg->FindInt32("key", &key) == B_OK) { 361 _KeyEvent((SDL_Scancode)key, NULL, 0, SDL_PRESSED); 362 } 363 break; 364 365 case B_KEY_UP: 366 case B_UNMAPPED_KEY_UP: /* modifier keys are unmapped */ 367 if (msg->FindInt32("key", &key) == B_OK) { 368 _KeyEvent(key, NULL, 0, SDL_RELEASED); 369 } 370 break; 371 372 default: 373 /* move it after switch{} so it's always handled 374 that way we keep Haiku features like: 375 - CTRL+Q to close window (and other shortcuts) 376 - PrintScreen to make screenshot into /boot/home 377 - etc.. */ 378 /* BDirectWindow::DispatchMessage(msg, target); */ 379 break; 380 } 381 382 BDirectWindow::DispatchMessage(msg, target); 383 } 384 385 /* Handle command messages */ 386 virtual void MessageReceived(BMessage* message) { 387 switch (message->what) { 388 /* Handle commands from SDL */ 389 case BWIN_SET_TITLE: 390 _SetTitle(message); 391 break; 392 case BWIN_MOVE_WINDOW: 393 _MoveTo(message); 394 break; 395 case BWIN_RESIZE_WINDOW: 396 _ResizeTo(message); 397 break; 398 case BWIN_SET_BORDERED: 399 _SetBordered(message); 400 break; 401 case BWIN_SET_RESIZABLE: 402 _SetResizable(message); 403 break; 404 case BWIN_SHOW_WINDOW: 405 Show(); 406 break; 407 case BWIN_HIDE_WINDOW: 408 Hide(); 409 break; 410 case BWIN_MAXIMIZE_WINDOW: 411 BWindow::Zoom(); 412 break; 413 case BWIN_MINIMIZE_WINDOW: 414 Minimize(true); 415 break; 416 case BWIN_RESTORE_WINDOW: 417 _Restore(); 418 break; 419 case BWIN_FULLSCREEN: 420 _SetFullScreen(message); 421 break; 422 default: 423 /* Perform normal message handling */ 424 BDirectWindow::MessageReceived(message); 425 break; 426 } 427 428 } 429 430 431 432 /* Accessor methods */ 433 bool IsShown() { return _shown; } 434 int32 GetID() { return _id; } 435 uint32 GetRowBytes() { return _row_bytes; } 436 int32 GetFbX() { return _bounds.left; } 437 int32 GetFbY() { return _bounds.top; } 438 bool ConnectionEnabled() { return !_connection_disabled; } 439 bool Connected() { return _connected; } 440 clipping_rect *GetClips() { return _clips; } 441 int32 GetNumClips() { return _num_clips; } 442 uint8* GetBufferPx() { return _bits; } 443 int32 GetBytesPerPx() { return _bytes_per_px; } 444 bool CanTrashWindowBuffer() { return _trash_window_buffer; } 445 bool BufferExists() { return _buffer_created; } 446 bool BufferIsDirty() { return _buffer_dirty; } 447 BBitmap *GetBitmap() { return _bitmap; } 448#if SDL_VIDEO_OPENGL 449 BGLView *GetGLView() { return _SDL_GLView; } 450 Uint32 GetGLType() { return _gl_type; } 451#endif 452 453 /* Setter methods */ 454 void SetID(int32 id) { _id = id; } 455 void SetBufferExists(bool bufferExists) { _buffer_created = bufferExists; } 456 void LockBuffer() { _buffer_locker->Lock(); } 457 void UnlockBuffer() { _buffer_locker->Unlock(); } 458 void SetBufferDirty(bool bufferDirty) { _buffer_dirty = bufferDirty; } 459 void SetTrashBuffer(bool trash) { _trash_window_buffer = trash; } 460 void SetBitmap(BBitmap *bitmap) { _bitmap = bitmap; } 461 462 463private: 464 /* Event redirection */ 465 void _MouseMotionEvent(BPoint &where, int32 transit) { 466 if(transit == B_EXITED_VIEW) { 467 /* Change mouse focus */ 468 if(_mouse_focused) { 469 _MouseFocusEvent(false); 470 } 471 } else { 472 /* Change mouse focus */ 473 if (!_mouse_focused) { 474 _MouseFocusEvent(true); 475 } 476 BMessage msg(BAPP_MOUSE_MOVED); 477 msg.AddInt32("x", (int)where.x); 478 msg.AddInt32("y", (int)where.y); 479 480 _PostWindowEvent(msg); 481 } 482 } 483 484 void _MouseFocusEvent(bool focusGained) { 485 _mouse_focused = focusGained; 486 BMessage msg(BAPP_MOUSE_FOCUS); 487 msg.AddBool("focusGained", focusGained); 488 _PostWindowEvent(msg); 489 490/* FIXME: Why were these here? 491 if false: be_app->SetCursor(B_HAND_CURSOR); 492 if true: SDL_SetCursor(NULL); */ 493 } 494 495 void _MouseButtonEvent(int32 buttons) { 496 int32 buttonStateChange = buttons ^ _last_buttons; 497 498 /* Make sure at least one button has changed state */ 499 if( !(buttonStateChange) ) { 500 return; 501 } 502 503 /* Add any mouse button events */ 504 if(buttonStateChange & B_PRIMARY_MOUSE_BUTTON) { 505 _SendMouseButton(SDL_BUTTON_LEFT, buttons & 506 B_PRIMARY_MOUSE_BUTTON); 507 } 508 if(buttonStateChange & B_SECONDARY_MOUSE_BUTTON) { 509 _SendMouseButton(SDL_BUTTON_RIGHT, buttons & 510 B_PRIMARY_MOUSE_BUTTON); 511 } 512 if(buttonStateChange & B_TERTIARY_MOUSE_BUTTON) { 513 _SendMouseButton(SDL_BUTTON_MIDDLE, buttons & 514 B_PRIMARY_MOUSE_BUTTON); 515 } 516 517 _last_buttons = buttons; 518 } 519 520 void _SendMouseButton(int32 button, int32 state) { 521 BMessage msg(BAPP_MOUSE_BUTTON); 522 msg.AddInt32("button-id", button); 523 msg.AddInt32("button-state", state); 524 _PostWindowEvent(msg); 525 } 526 527 void _MouseWheelEvent(int32 x, int32 y) { 528 /* Create a message to pass along to the BeApp thread */ 529 BMessage msg(BAPP_MOUSE_WHEEL); 530 msg.AddInt32("xticks", x); 531 msg.AddInt32("yticks", y); 532 _PostWindowEvent(msg); 533 } 534 535 void _KeyEvent(int32 keyCode, const int8 *keyUtf8, const ssize_t & len, int32 keyState) { 536 /* Create a message to pass along to the BeApp thread */ 537 BMessage msg(BAPP_KEY); 538 msg.AddInt32("key-state", keyState); 539 msg.AddInt32("key-scancode", keyCode); 540 if (keyUtf8 != NULL) { 541 msg.AddData("key-utf8", B_INT8_TYPE, (const void*)keyUtf8, len); 542 } 543 be_app->PostMessage(&msg); 544 } 545 546 void _RepaintEvent() { 547 /* Force a repaint: Call the SDL exposed event */ 548 BMessage msg(BAPP_REPAINT); 549 _PostWindowEvent(msg); 550 } 551 void _PostWindowEvent(BMessage &msg) { 552 msg.AddInt32("window-id", _id); 553 be_app->PostMessage(&msg); 554 } 555 556 /* Command methods (functions called upon by SDL) */ 557 void _SetTitle(BMessage *msg) { 558 const char *title; 559 if( 560 msg->FindString("window-title", &title) != B_OK 561 ) { 562 return; 563 } 564 SetTitle(title); 565 } 566 567 void _MoveTo(BMessage *msg) { 568 int32 x, y; 569 if( 570 msg->FindInt32("window-x", &x) != B_OK || 571 msg->FindInt32("window-y", &y) != B_OK 572 ) { 573 return; 574 } 575 MoveTo(x, y); 576 } 577 578 void _ResizeTo(BMessage *msg) { 579 int32 w, h; 580 if( 581 msg->FindInt32("window-w", &w) != B_OK || 582 msg->FindInt32("window-h", &h) != B_OK 583 ) { 584 return; 585 } 586 ResizeTo(w, h); 587 } 588 589 void _SetBordered(BMessage *msg) { 590 bool bEnabled; 591 if(msg->FindBool("window-border", &bEnabled) != B_OK) { 592 return; 593 } 594 SetLook(bEnabled ? B_TITLED_WINDOW_LOOK : B_NO_BORDER_WINDOW_LOOK); 595 } 596 597 void _SetResizable(BMessage *msg) { 598 bool bEnabled; 599 if(msg->FindBool("window-resizable", &bEnabled) != B_OK) { 600 return; 601 } 602 if (bEnabled) { 603 SetFlags(Flags() & ~(B_NOT_RESIZABLE | B_NOT_ZOOMABLE)); 604 } else { 605 SetFlags(Flags() | (B_NOT_RESIZABLE | B_NOT_ZOOMABLE)); 606 } 607 } 608 609 void _Restore() { 610 if(IsMinimized()) { 611 Minimize(false); 612 } else if(IsHidden()) { 613 Show(); 614 } else if(_prev_frame != NULL) { /* Zoomed */ 615 MoveTo(_prev_frame->left, _prev_frame->top); 616 ResizeTo(_prev_frame->Width(), _prev_frame->Height()); 617 } 618 } 619 620 void _SetFullScreen(BMessage *msg) { 621 bool fullscreen; 622 if( 623 msg->FindBool("fullscreen", &fullscreen) != B_OK 624 ) { 625 return; 626 } 627 SetFullScreen(fullscreen); 628 } 629 630 /* Members */ 631#if SDL_VIDEO_OPENGL 632 BGLView * _SDL_GLView; 633 Uint32 _gl_type; 634#endif 635 636 int32 _last_buttons; 637 int32 _id; /* Window id used by SDL_BApp */ 638 bool _mouse_focused; /* Does this window have mouse focus? */ 639 bool _shown; 640 bool _inhibit_resize; 641 642 BRect *_prev_frame; /* Previous position and size of the window */ 643 644 /* Framebuffer members */ 645 bool _connected, 646 _connection_disabled, 647 _buffer_created, 648 _buffer_dirty, 649 _trash_window_buffer; 650 uint8 *_bits; 651 uint32 _row_bytes; 652 clipping_rect _bounds; 653 BLocker *_buffer_locker; 654 clipping_rect *_clips; 655 int32 _num_clips; 656 int32 _bytes_per_px; 657 thread_id _draw_thread_id; 658 659 BBitmap *_bitmap; 660}; 661 662 663/* FIXME: 664 * An explanation of framebuffer flags. 665 * 666 * _connected - Original variable used to let the drawing thread know 667 * when changes are being made to the other framebuffer 668 * members. 669 * _connection_disabled - Used to signal to the drawing thread that the window 670 * is closing, and the thread should exit. 671 * _buffer_created - True if the current buffer is valid 672 * _buffer_dirty - True if the window should be redrawn. 673 * _trash_window_buffer - True if the window buffer needs to be trashed partway 674 * through a draw cycle. Occurs when the previous 675 * buffer provided by DirectConnected() is invalidated. 676 */ 677#endif /* SDL_BWin_h_ */ 678 679/* vi: set ts=4 sw=4 expandtab: */ 680
[FILE END]
(C) 2025 0x4248 (C) 2025 4248 Media and 4248 Systems, All part of 0x4248 See LICENCE files for more information. Not all files are by 0x4248 always check Licencing.