src/video/haiku/SDL_BWin.h
author Sam Lantinga <slouken@libsdl.org>
Fri, 09 Dec 2016 01:47:43 -0800
changeset 10690 23a825f341e6
parent 10555 476a717c10cf
child 10737 3406a0f8b041
permissions -rw-r--r--
Fixed bug 3513 - SDL_GL_SwapWindow does not return error status

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