diff options
Diffstat (limited to 'Source/external/SDL2/src/video/directfb/SDL_DirectFB_WM.c')
-rw-r--r-- | Source/external/SDL2/src/video/directfb/SDL_DirectFB_WM.c | 413 |
1 files changed, 413 insertions, 0 deletions
diff --git a/Source/external/SDL2/src/video/directfb/SDL_DirectFB_WM.c b/Source/external/SDL2/src/video/directfb/SDL_DirectFB_WM.c new file mode 100644 index 0000000..d9d0c3a --- /dev/null +++ b/Source/external/SDL2/src/video/directfb/SDL_DirectFB_WM.c @@ -0,0 +1,413 @@ +/* + Simple DirectMedia Layer + Copyright (C) 1997-2018 Sam Lantinga <slouken@libsdl.org> + + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + 3. This notice may not be removed or altered from any source distribution. +*/ +#include "../../SDL_internal.h" + +#if SDL_VIDEO_DRIVER_DIRECTFB + +#include "SDL_DirectFB_video.h" +#include "SDL_DirectFB_window.h" + +#include "../../events/SDL_windowevents_c.h" + +#define COLOR_EXPAND(col) col.r, col.g, col.b, col.a + +static DFB_Theme theme_std = { + 4, 4, 8, 8, + {255, 200, 200, 200}, + 24, + {255, 0, 0, 255}, + 16, + {255, 255, 255, 255}, + "/usr/share/fonts/truetype/freefont/FreeSans.ttf", + {255, 255, 0, 0}, + {255, 255, 255, 0}, +}; + +static DFB_Theme theme_none = { + 0, 0, 0, 0, + {0, 0, 0, 0}, + 0, + {0, 0, 0, 0}, + 0, + {0, 0, 0, 0}, + NULL +}; + +static void +DrawTriangle(IDirectFBSurface * s, int down, int x, int y, int w) +{ + int x1, x2, x3; + int y1, y2, y3; + + if (down) { + x1 = x + w / 2; + x2 = x; + x3 = x + w; + y1 = y + w; + y2 = y; + y3 = y; + } else { + x1 = x + w / 2; + x2 = x; + x3 = x + w; + y1 = y; + y2 = y + w; + y3 = y + w; + } + s->FillTriangle(s, x1, y1, x2, y2, x3, y3); +} + +static void +LoadFont(_THIS, SDL_Window * window) +{ + SDL_DFB_DEVICEDATA(_this); + SDL_DFB_WINDOWDATA(window); + + if (windata->font != NULL) { + SDL_DFB_RELEASE(windata->font); + windata->font = NULL; + SDL_DFB_CHECK(windata->window_surface->SetFont(windata->window_surface, windata->font)); + } + + if (windata->theme.font != NULL) + { + DFBFontDescription fdesc; + + SDL_zero(fdesc); + fdesc.flags = DFDESC_HEIGHT; + fdesc.height = windata->theme.font_size; + SDL_DFB_CHECK(devdata-> + dfb->CreateFont(devdata->dfb, windata->theme.font, + &fdesc, &windata->font)); + SDL_DFB_CHECK(windata->window_surface->SetFont(windata->window_surface, windata->font)); + } +} + +static void +DrawCraption(_THIS, IDirectFBSurface * s, int x, int y, char *text) +{ + DFBSurfaceTextFlags flags; + + flags = DSTF_CENTER | DSTF_TOP; + + s->DrawString(s, text, -1, x, y, flags); +} + +void +DirectFB_WM_RedrawLayout(_THIS, SDL_Window * window) +{ + SDL_DFB_WINDOWDATA(window); + IDirectFBSurface *s = windata->window_surface; + DFB_Theme *t = &windata->theme; + int i; + int d = (t->caption_size - t->font_size) / 2; + int x, y, w; + + + if (!windata->is_managed || (window->flags & SDL_WINDOW_FULLSCREEN)) + return; + + SDL_DFB_CHECK(s->SetSrcBlendFunction(s, DSBF_ONE)); + SDL_DFB_CHECK(s->SetDstBlendFunction(s, DSBF_ZERO)); + SDL_DFB_CHECK(s->SetDrawingFlags(s, DSDRAW_NOFX)); + SDL_DFB_CHECK(s->SetBlittingFlags(s, DSBLIT_NOFX)); + + LoadFont(_this, window); + /* s->SetDrawingFlags(s, DSDRAW_BLEND); */ + s->SetColor(s, COLOR_EXPAND(t->frame_color)); + /* top */ + for (i = 0; i < t->top_size; i++) + s->DrawLine(s, 0, i, windata->size.w, i); + /* bottom */ + for (i = windata->size.h - t->bottom_size; i < windata->size.h; i++) + s->DrawLine(s, 0, i, windata->size.w, i); + /* left */ + for (i = 0; i < t->left_size; i++) + s->DrawLine(s, i, 0, i, windata->size.h); + /* right */ + for (i = windata->size.w - t->right_size; i < windata->size.w; i++) + s->DrawLine(s, i, 0, i, windata->size.h); + /* Caption */ + s->SetColor(s, COLOR_EXPAND(t->caption_color)); + s->FillRectangle(s, t->left_size, t->top_size, windata->client.w, + t->caption_size); + /* Close Button */ + w = t->caption_size; + x = windata->size.w - t->right_size - w + d; + y = t->top_size + d; + s->SetColor(s, COLOR_EXPAND(t->close_color)); + DrawTriangle(s, 1, x, y, w - 2 * d); + /* Max Button */ + s->SetColor(s, COLOR_EXPAND(t->max_color)); + DrawTriangle(s, window->flags & SDL_WINDOW_MAXIMIZED ? 1 : 0, x - w, + y, w - 2 * d); + + /* Caption */ + if (*window->title) { + s->SetColor(s, COLOR_EXPAND(t->font_color)); + DrawCraption(_this, s, (x - w) / 2, t->top_size + d, window->title); + } + /* Icon */ + if (windata->icon) { + DFBRectangle dr; + + dr.x = t->left_size + d; + dr.y = t->top_size + d; + dr.w = w - 2 * d; + dr.h = w - 2 * d; + s->SetBlittingFlags(s, DSBLIT_BLEND_ALPHACHANNEL); + + s->StretchBlit(s, windata->icon, NULL, &dr); + } + windata->wm_needs_redraw = 0; +} + +DFBResult +DirectFB_WM_GetClientSize(_THIS, SDL_Window * window, int *cw, int *ch) +{ + SDL_DFB_WINDOWDATA(window); + IDirectFBWindow *dfbwin = windata->dfbwin; + + SDL_DFB_CHECK(dfbwin->GetSize(dfbwin, cw, ch)); + dfbwin->GetSize(dfbwin, cw, ch); + *cw -= windata->theme.left_size + windata->theme.right_size; + *ch -= + windata->theme.top_size + windata->theme.caption_size + + windata->theme.bottom_size; + return DFB_OK; +} + +void +DirectFB_WM_AdjustWindowLayout(SDL_Window * window, int flags, int w, int h) +{ + SDL_DFB_WINDOWDATA(window); + + if (!windata->is_managed) + windata->theme = theme_none; + else if (flags & SDL_WINDOW_BORDERLESS) + /* desc.caps |= DWCAPS_NODECORATION;) */ + windata->theme = theme_none; + else if (flags & SDL_WINDOW_FULLSCREEN) { + windata->theme = theme_none; + } else if (flags & SDL_WINDOW_MAXIMIZED) { + windata->theme = theme_std; + windata->theme.left_size = 0; + windata->theme.right_size = 0; + windata->theme.top_size = 0; + windata->theme.bottom_size = 0; + } else { + windata->theme = theme_std; + } + + windata->client.x = windata->theme.left_size; + windata->client.y = windata->theme.top_size + windata->theme.caption_size; + windata->client.w = w; + windata->client.h = h; + windata->size.w = + w + windata->theme.left_size + windata->theme.right_size; + windata->size.h = + h + windata->theme.top_size + + windata->theme.caption_size + windata->theme.bottom_size; +} + + +enum +{ + WM_POS_NONE = 0x00, + WM_POS_CAPTION = 0x01, + WM_POS_CLOSE = 0x02, + WM_POS_MAX = 0x04, + WM_POS_LEFT = 0x08, + WM_POS_RIGHT = 0x10, + WM_POS_TOP = 0x20, + WM_POS_BOTTOM = 0x40, +}; + +static int +WMIsClient(DFB_WindowData * p, int x, int y) +{ + x -= p->client.x; + y -= p->client.y; + if (x < 0 || y < 0) + return 0; + if (x >= p->client.w || y >= p->client.h) + return 0; + return 1; +} + +static int +WMPos(DFB_WindowData * p, int x, int y) +{ + int pos = WM_POS_NONE; + + if (!WMIsClient(p, x, y)) { + if (y < p->theme.top_size) { + pos |= WM_POS_TOP; + } else if (y < p->client.y) { + if (x < + p->size.w - p->theme.right_size - 2 * p->theme.caption_size) { + pos |= WM_POS_CAPTION; + } else if (x < + p->size.w - p->theme.right_size - + p->theme.caption_size) { + pos |= WM_POS_MAX; + } else { + pos |= WM_POS_CLOSE; + } + } else if (y >= p->size.h - p->theme.bottom_size) { + pos |= WM_POS_BOTTOM; + } + if (x < p->theme.left_size) { + pos |= WM_POS_LEFT; + } else if (x >= p->size.w - p->theme.right_size) { + pos |= WM_POS_RIGHT; + } + } + return pos; +} + +int +DirectFB_WM_ProcessEvent(_THIS, SDL_Window * window, DFBWindowEvent * evt) +{ + SDL_DFB_DEVICEDATA(_this); + SDL_DFB_WINDOWDATA(window); + DFB_WindowData *gwindata = ((devdata->grabbed_window) ? (DFB_WindowData *) ((devdata->grabbed_window)->driverdata) : NULL); + IDirectFBWindow *dfbwin = windata->dfbwin; + DFBWindowOptions wopts; + + if (!windata->is_managed) + return 0; + + SDL_DFB_CHECK(dfbwin->GetOptions(dfbwin, &wopts)); + + switch (evt->type) { + case DWET_BUTTONDOWN: + if (evt->buttons & DIBM_LEFT) { + int pos = WMPos(windata, evt->x, evt->y); + switch (pos) { + case WM_POS_NONE: + return 0; + case WM_POS_CLOSE: + windata->wm_grab = WM_POS_NONE; + SDL_SendWindowEvent(window, SDL_WINDOWEVENT_CLOSE, 0, + 0); + return 1; + case WM_POS_MAX: + windata->wm_grab = WM_POS_NONE; + if (window->flags & SDL_WINDOW_MAXIMIZED) { + SDL_RestoreWindow(window); + } else { + SDL_MaximizeWindow(window); + } + return 1; + case WM_POS_CAPTION: + if (!(wopts & DWOP_KEEP_STACKING)) { + DirectFB_RaiseWindow(_this, window); + } + if (window->flags & SDL_WINDOW_MAXIMIZED) + return 1; + /* fall through */ + default: + windata->wm_grab = pos; + if (gwindata != NULL) + SDL_DFB_CHECK(gwindata->dfbwin->UngrabPointer(gwindata->dfbwin)); + SDL_DFB_CHECK(dfbwin->GrabPointer(dfbwin)); + windata->wm_lastx = evt->cx; + windata->wm_lasty = evt->cy; + } + } + return 1; + case DWET_BUTTONUP: + if (!windata->wm_grab) + return 0; + if (!(evt->buttons & DIBM_LEFT)) { + if (windata->wm_grab & (WM_POS_RIGHT | WM_POS_BOTTOM)) { + int dx = evt->cx - windata->wm_lastx; + int dy = evt->cy - windata->wm_lasty; + + if (!(wopts & DWOP_KEEP_SIZE)) { + int cw, ch; + if ((windata->wm_grab & (WM_POS_BOTTOM | WM_POS_RIGHT)) == WM_POS_BOTTOM) + dx = 0; + else if ((windata->wm_grab & (WM_POS_BOTTOM | WM_POS_RIGHT)) == WM_POS_RIGHT) + dy = 0; + SDL_DFB_CHECK(dfbwin->GetSize(dfbwin, &cw, &ch)); + + /* necessary to trigger an event - ugly */ + SDL_DFB_CHECK(dfbwin->DisableEvents(dfbwin, DWET_ALL)); + SDL_DFB_CHECK(dfbwin->Resize(dfbwin, cw + dx + 1, ch + dy)); + SDL_DFB_CHECK(dfbwin->EnableEvents(dfbwin, DWET_ALL)); + + SDL_DFB_CHECK(dfbwin->Resize(dfbwin, cw + dx, ch + dy)); + } + } + SDL_DFB_CHECK(dfbwin->UngrabPointer(dfbwin)); + if (gwindata != NULL) + SDL_DFB_CHECK(gwindata->dfbwin->GrabPointer(gwindata->dfbwin)); + windata->wm_grab = WM_POS_NONE; + return 1; + } + break; + case DWET_MOTION: + if (!windata->wm_grab) + return 0; + if (evt->buttons & DIBM_LEFT) { + int dx = evt->cx - windata->wm_lastx; + int dy = evt->cy - windata->wm_lasty; + + if (windata->wm_grab & WM_POS_CAPTION) { + if (!(wopts & DWOP_KEEP_POSITION)) + SDL_DFB_CHECK(dfbwin->Move(dfbwin, dx, dy)); + } + if (windata->wm_grab & (WM_POS_RIGHT | WM_POS_BOTTOM)) { + if (!(wopts & DWOP_KEEP_SIZE)) { + int cw, ch; + + /* Make sure all events are disabled for this operation ! */ + SDL_DFB_CHECK(dfbwin->DisableEvents(dfbwin, DWET_ALL)); + + if ((windata->wm_grab & (WM_POS_BOTTOM | WM_POS_RIGHT)) == WM_POS_BOTTOM) + dx = 0; + else if ((windata->wm_grab & (WM_POS_BOTTOM | WM_POS_RIGHT)) == WM_POS_RIGHT) + dy = 0; + + SDL_DFB_CHECK(dfbwin->GetSize(dfbwin, &cw, &ch)); + SDL_DFB_CHECK(dfbwin->Resize(dfbwin, cw + dx, ch + dy)); + + SDL_DFB_CHECK(dfbwin->EnableEvents(dfbwin, DWET_ALL)); + } + } + windata->wm_lastx = evt->cx; + windata->wm_lasty = evt->cy; + return 1; + } + break; + case DWET_KEYDOWN: + break; + case DWET_KEYUP: + break; + default: + ; + } + return 0; +} + +#endif /* SDL_VIDEO_DRIVER_DIRECTFB */ |