src/video/directfb/SDL_DirectFB_WM.c
author Gabriel Jacobo <gabomdq@gmail.com>
Wed, 21 Aug 2013 09:47:10 -0300
changeset 7678 286c42d7c5ed
parent 7677 871d43c6968a
child 8093 b43765095a6f
permissions -rw-r--r--
OCD fixes: Adds a space after /* (glory to regular expressions!)
     1 /*
     2   Simple DirectMedia Layer
     3   Copyright (C) 1997-2013 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 #include "SDL_config.h"
    22 
    23 #if SDL_VIDEO_DRIVER_DIRECTFB
    24 
    25 #include "SDL_DirectFB_video.h"
    26 #include "SDL_DirectFB_window.h"
    27 
    28 #include "../../events/SDL_windowevents_c.h"
    29 
    30 #define COLOR_EXPAND(col) col.r, col.g, col.b, col.a
    31 
    32 static DFB_Theme theme_std = {
    33     4, 4, 8, 8,
    34     {255, 200, 200, 200},
    35     24,
    36     {255, 0, 0, 255},
    37     16,
    38     {255, 255, 255, 255},
    39     "/usr/share/fonts/truetype/freefont/FreeSans.ttf",
    40     {255, 255, 0, 0},
    41     {255, 255, 255, 0},
    42 };
    43 
    44 static DFB_Theme theme_none = {
    45     0, 0, 0, 0,
    46     {0, 0, 0, 0},
    47     0,
    48     {0, 0, 0, 0},
    49     0,
    50     {0, 0, 0, 0},
    51     NULL
    52 };
    53 
    54 static void
    55 DrawTriangle(IDirectFBSurface * s, int down, int x, int y, int w)
    56 {
    57     int x1, x2, x3;
    58     int y1, y2, y3;
    59 
    60     if (down) {
    61         x1 = x + w / 2;
    62         x2 = x;
    63         x3 = x + w;
    64         y1 = y + w;
    65         y2 = y;
    66         y3 = y;
    67     } else {
    68         x1 = x + w / 2;
    69         x2 = x;
    70         x3 = x + w;
    71         y1 = y;
    72         y2 = y + w;
    73         y3 = y + w;
    74     }
    75     s->FillTriangle(s, x1, y1, x2, y2, x3, y3);
    76 }
    77 
    78 static void
    79 LoadFont(_THIS, SDL_Window * window)
    80 {
    81     SDL_DFB_DEVICEDATA(_this);
    82     SDL_DFB_WINDOWDATA(window);
    83 
    84     if (windata->font != NULL) {
    85         SDL_DFB_RELEASE(windata->font);
    86         windata->font = NULL;
    87         SDL_DFB_CHECK(windata->window_surface->SetFont(windata->window_surface, windata->font));
    88     }
    89 
    90     if (windata->theme.font != NULL)
    91     {
    92         DFBFontDescription fdesc;
    93 
    94         SDL_zero(fdesc);
    95         fdesc.flags = DFDESC_HEIGHT;
    96         fdesc.height = windata->theme.font_size;
    97         SDL_DFB_CHECK(devdata->
    98                       dfb->CreateFont(devdata->dfb, windata->theme.font,
    99                                       &fdesc, &windata->font));
   100         SDL_DFB_CHECK(windata->window_surface->SetFont(windata->window_surface, windata->font));
   101     }
   102 }
   103 
   104 static void
   105 DrawCraption(_THIS, IDirectFBSurface * s, int x, int y, char *text)
   106 {
   107     DFBSurfaceTextFlags flags;
   108 
   109     flags = DSTF_CENTER | DSTF_TOP;
   110 
   111     s->DrawString(s, text, -1, x, y, flags);
   112 }
   113 
   114 void
   115 DirectFB_WM_RedrawLayout(_THIS, SDL_Window * window)
   116 {
   117     SDL_DFB_WINDOWDATA(window);
   118     IDirectFBSurface *s = windata->window_surface;
   119     DFB_Theme *t = &windata->theme;
   120     int i;
   121     int d = (t->caption_size - t->font_size) / 2;
   122     int x, y, w;
   123 
   124 
   125     if (!windata->is_managed || (window->flags & SDL_WINDOW_FULLSCREEN))
   126         return;
   127 
   128     SDL_DFB_CHECK(s->SetSrcBlendFunction(s, DSBF_ONE));
   129     SDL_DFB_CHECK(s->SetDstBlendFunction(s, DSBF_ZERO));
   130     SDL_DFB_CHECK(s->SetDrawingFlags(s, DSDRAW_NOFX));
   131     SDL_DFB_CHECK(s->SetBlittingFlags(s, DSBLIT_NOFX));
   132 
   133     LoadFont(_this, window);
   134     /* s->SetDrawingFlags(s, DSDRAW_BLEND); */
   135     s->SetColor(s, COLOR_EXPAND(t->frame_color));
   136     /* top */
   137     for (i = 0; i < t->top_size; i++)
   138         s->DrawLine(s, 0, i, windata->size.w, i);
   139     /* bottom */
   140     for (i = windata->size.h - t->bottom_size; i < windata->size.h; i++)
   141         s->DrawLine(s, 0, i, windata->size.w, i);
   142     /* left */
   143     for (i = 0; i < t->left_size; i++)
   144         s->DrawLine(s, i, 0, i, windata->size.h);
   145     /* right */
   146     for (i = windata->size.w - t->right_size; i < windata->size.w; i++)
   147         s->DrawLine(s, i, 0, i, windata->size.h);
   148     /* Caption */
   149     s->SetColor(s, COLOR_EXPAND(t->caption_color));
   150     s->FillRectangle(s, t->left_size, t->top_size, windata->client.w,
   151                      t->caption_size);
   152     /* Close Button */
   153     w = t->caption_size;
   154     x = windata->size.w - t->right_size - w + d;
   155     y = t->top_size + d;
   156     s->SetColor(s, COLOR_EXPAND(t->close_color));
   157     DrawTriangle(s, 1, x, y, w - 2 * d);
   158     /* Max Button */
   159     s->SetColor(s, COLOR_EXPAND(t->max_color));
   160     DrawTriangle(s, window->flags & SDL_WINDOW_MAXIMIZED ? 1 : 0, x - w,
   161                y, w - 2 * d);
   162 
   163     /* Caption */
   164     if (window->title) {
   165         s->SetColor(s, COLOR_EXPAND(t->font_color));
   166         DrawCraption(_this, s, (x - w) / 2, t->top_size + d, window->title);
   167     }
   168     /* Icon */
   169     if (windata->icon) {
   170         DFBRectangle dr;
   171 
   172         dr.x = t->left_size + d;
   173         dr.y = t->top_size + d;
   174         dr.w = w - 2 * d;
   175         dr.h = w - 2 * d;
   176         s->SetBlittingFlags(s, DSBLIT_BLEND_ALPHACHANNEL);
   177 
   178         s->StretchBlit(s, windata->icon, NULL, &dr);
   179     }
   180     windata->wm_needs_redraw = 0;
   181 }
   182 
   183 DFBResult
   184 DirectFB_WM_GetClientSize(_THIS, SDL_Window * window, int *cw, int *ch)
   185 {
   186     SDL_DFB_WINDOWDATA(window);
   187     IDirectFBWindow *dfbwin = windata->dfbwin;
   188 
   189     SDL_DFB_CHECK(dfbwin->GetSize(dfbwin, cw, ch));
   190     dfbwin->GetSize(dfbwin, cw, ch);
   191     *cw -= windata->theme.left_size + windata->theme.right_size;
   192     *ch -=
   193         windata->theme.top_size + windata->theme.caption_size +
   194         windata->theme.bottom_size;
   195     return DFB_OK;
   196 }
   197 
   198 void
   199 DirectFB_WM_AdjustWindowLayout(SDL_Window * window, int flags, int w, int h)
   200 {
   201     SDL_DFB_WINDOWDATA(window);
   202 
   203     if (!windata->is_managed)
   204         windata->theme = theme_none;
   205     else if (flags & SDL_WINDOW_BORDERLESS)
   206         /* desc.caps |= DWCAPS_NODECORATION;) */
   207         windata->theme = theme_none;
   208     else if (flags & SDL_WINDOW_FULLSCREEN) {
   209         windata->theme = theme_none;
   210     } else if (flags & SDL_WINDOW_MAXIMIZED) {
   211         windata->theme = theme_std;
   212         windata->theme.left_size = 0;
   213         windata->theme.right_size = 0;
   214         windata->theme.top_size = 0;
   215         windata->theme.bottom_size = 0;
   216     } else {
   217         windata->theme = theme_std;
   218     }
   219 
   220     windata->client.x = windata->theme.left_size;
   221     windata->client.y = windata->theme.top_size + windata->theme.caption_size;
   222     windata->client.w = w;
   223     windata->client.h = h;
   224     windata->size.w =
   225         w + windata->theme.left_size + windata->theme.right_size;
   226     windata->size.h =
   227         h + windata->theme.top_size +
   228         windata->theme.caption_size + windata->theme.bottom_size;
   229 }
   230 
   231 
   232 enum
   233 {
   234     WM_POS_NONE = 0x00,
   235     WM_POS_CAPTION = 0x01,
   236     WM_POS_CLOSE = 0x02,
   237     WM_POS_MAX = 0x04,
   238     WM_POS_LEFT = 0x08,
   239     WM_POS_RIGHT = 0x10,
   240     WM_POS_TOP = 0x20,
   241     WM_POS_BOTTOM = 0x40,
   242 };
   243 
   244 static int
   245 WMIsClient(DFB_WindowData * p, int x, int y)
   246 {
   247     x -= p->client.x;
   248     y -= p->client.y;
   249     if (x < 0 || y < 0)
   250         return 0;
   251     if (x >= p->client.w || y >= p->client.h)
   252         return 0;
   253     return 1;
   254 }
   255 
   256 static int
   257 WMPos(DFB_WindowData * p, int x, int y)
   258 {
   259     int pos = WM_POS_NONE;
   260 
   261     if (!WMIsClient(p, x, y)) {
   262         if (y < p->theme.top_size) {
   263             pos |= WM_POS_TOP;
   264         } else if (y < p->client.y) {
   265             if (x <
   266                 p->size.w - p->theme.right_size - 2 * p->theme.caption_size) {
   267                 pos |= WM_POS_CAPTION;
   268             } else if (x <
   269                        p->size.w - p->theme.right_size -
   270                        p->theme.caption_size) {
   271                 pos |= WM_POS_MAX;
   272             } else {
   273                 pos |= WM_POS_CLOSE;
   274             }
   275         } else if (y >= p->size.h - p->theme.bottom_size) {
   276             pos |= WM_POS_BOTTOM;
   277         }
   278         if (x < p->theme.left_size) {
   279             pos |= WM_POS_LEFT;
   280         } else if (x >= p->size.w - p->theme.right_size) {
   281             pos |= WM_POS_RIGHT;
   282         }
   283     }
   284     return pos;
   285 }
   286 
   287 int
   288 DirectFB_WM_ProcessEvent(_THIS, SDL_Window * window, DFBWindowEvent * evt)
   289 {
   290     SDL_DFB_DEVICEDATA(_this);
   291     SDL_DFB_WINDOWDATA(window);
   292     DFB_WindowData *gwindata = ((devdata->grabbed_window) ? (DFB_WindowData *) ((devdata->grabbed_window)->driverdata) : NULL);
   293     IDirectFBWindow *dfbwin = windata->dfbwin;
   294     DFBWindowOptions wopts;
   295 
   296     if (!windata->is_managed)
   297         return 0;
   298 
   299     SDL_DFB_CHECK(dfbwin->GetOptions(dfbwin, &wopts));
   300 
   301     switch (evt->type) {
   302     case DWET_BUTTONDOWN:
   303         if (evt->buttons & DIBM_LEFT) {
   304             int pos = WMPos(windata, evt->x, evt->y);
   305             switch (pos) {
   306             case WM_POS_NONE:
   307                 return 0;
   308             case WM_POS_CLOSE:
   309                 windata->wm_grab = WM_POS_NONE;
   310                 SDL_SendWindowEvent(window, SDL_WINDOWEVENT_CLOSE, 0,
   311                                     0);
   312                 return 1;
   313             case WM_POS_MAX:
   314                 windata->wm_grab = WM_POS_NONE;
   315                 if (window->flags & SDL_WINDOW_MAXIMIZED) {
   316                     SDL_RestoreWindow(window);
   317                 } else {
   318                     SDL_MaximizeWindow(window);
   319                 }
   320                 return 1;
   321             case WM_POS_CAPTION:
   322                 if (!(wopts & DWOP_KEEP_STACKING)) {
   323                     DirectFB_RaiseWindow(_this, window);
   324                 }
   325                 if (window->flags & SDL_WINDOW_MAXIMIZED)
   326                     return 1;
   327                 /* fall through */
   328             default:
   329                 windata->wm_grab = pos;
   330                 if (gwindata != NULL)
   331                     SDL_DFB_CHECK(gwindata->dfbwin->UngrabPointer(gwindata->dfbwin));
   332                 SDL_DFB_CHECK(dfbwin->GrabPointer(dfbwin));
   333                 windata->wm_lastx = evt->cx;
   334                 windata->wm_lasty = evt->cy;
   335             }
   336         }
   337         return 1;
   338     case DWET_BUTTONUP:
   339         if (!windata->wm_grab)
   340             return 0;
   341         if (!(evt->buttons & DIBM_LEFT)) {
   342             if (windata->wm_grab & (WM_POS_RIGHT | WM_POS_BOTTOM)) {
   343                 int dx = evt->cx - windata->wm_lastx;
   344                 int dy = evt->cy - windata->wm_lasty;
   345 
   346                 if (!(wopts & DWOP_KEEP_SIZE)) {
   347                     int cw, ch;
   348                     if ((windata->wm_grab & (WM_POS_BOTTOM | WM_POS_RIGHT)) == WM_POS_BOTTOM)
   349                         dx = 0;
   350                     else if ((windata->wm_grab & (WM_POS_BOTTOM | WM_POS_RIGHT)) == WM_POS_RIGHT)
   351                         dy = 0;
   352                     SDL_DFB_CHECK(dfbwin->GetSize(dfbwin, &cw, &ch));
   353 
   354                     /* necessary to trigger an event - ugly */
   355                     SDL_DFB_CHECK(dfbwin->DisableEvents(dfbwin, DWET_ALL));
   356                     SDL_DFB_CHECK(dfbwin->Resize(dfbwin, cw + dx + 1, ch + dy));
   357                     SDL_DFB_CHECK(dfbwin->EnableEvents(dfbwin, DWET_ALL));
   358 
   359                     SDL_DFB_CHECK(dfbwin->Resize(dfbwin, cw + dx, ch + dy));
   360                 }
   361             }
   362             SDL_DFB_CHECK(dfbwin->UngrabPointer(dfbwin));
   363             if (gwindata != NULL)
   364                 SDL_DFB_CHECK(gwindata->dfbwin->GrabPointer(gwindata->dfbwin));
   365             windata->wm_grab = WM_POS_NONE;
   366             return 1;
   367         }
   368         break;
   369     case DWET_MOTION:
   370         if (!windata->wm_grab)
   371             return 0;
   372         if (evt->buttons & DIBM_LEFT) {
   373             int dx = evt->cx - windata->wm_lastx;
   374             int dy = evt->cy - windata->wm_lasty;
   375 
   376             if (windata->wm_grab & WM_POS_CAPTION) {
   377                 if (!(wopts & DWOP_KEEP_POSITION))
   378                     SDL_DFB_CHECK(dfbwin->Move(dfbwin, dx, dy));
   379             }
   380             if (windata->wm_grab & (WM_POS_RIGHT | WM_POS_BOTTOM)) {
   381                 if (!(wopts & DWOP_KEEP_SIZE)) {
   382                     int cw, ch;
   383 
   384                     /* Make sure all events are disabled for this operation ! */
   385                     SDL_DFB_CHECK(dfbwin->DisableEvents(dfbwin, DWET_ALL));
   386 
   387                     if ((windata->wm_grab & (WM_POS_BOTTOM | WM_POS_RIGHT)) == WM_POS_BOTTOM)
   388                         dx = 0;
   389                     else if ((windata->wm_grab & (WM_POS_BOTTOM | WM_POS_RIGHT)) == WM_POS_RIGHT)
   390                         dy = 0;
   391 
   392                     SDL_DFB_CHECK(dfbwin->GetSize(dfbwin, &cw, &ch));
   393                     SDL_DFB_CHECK(dfbwin->Resize(dfbwin, cw + dx, ch + dy));
   394 
   395                     SDL_DFB_CHECK(dfbwin->EnableEvents(dfbwin, DWET_ALL));
   396                 }
   397             }
   398             windata->wm_lastx = evt->cx;
   399             windata->wm_lasty = evt->cy;
   400             return 1;
   401         }
   402         break;
   403     case DWET_KEYDOWN:
   404         break;
   405     case DWET_KEYUP:
   406         break;
   407     default:
   408         ;
   409     }
   410     return 0;
   411 }
   412 
   413 #endif /* SDL_VIDEO_DRIVER_DIRECTFB */