src/video/haiku/SDL_BWin.h
author Sylvain Becker <sylvain.becker@gmail.com>
Thu, 23 May 2019 09:08:40 +0200
changeset 12751 06fa9a25d2a0
parent 12503 806492103856
permissions -rw-r--r--
Android: minimum size for IME, so that it takes focus

In API 28, 0 width views can't take focus, so if someone tries to position the IME without setting a width, they'll stop getting text events.

Tested on Android 9: with a 0 size, it would send correctly letters a, b, c, etc. but not numbers.
     1 /*
     2   Simple DirectMedia Layer
     3   Copyright (C) 1997-2019 Sam Lantinga <slouken@libsdl.org>
     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
    26 extern "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 
    49 enum 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 
    64 class 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 
   463 private:
   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: */