| /* |
| Simple DirectMedia Layer |
| Copyright (C) 1997-2020 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 */ |