2014-02-27 07:40:21 +04:00
|
|
|
/**
|
|
|
|
* FreeRDP: A Remote Desktop Protocol Implementation
|
|
|
|
* Windows Float Bar
|
|
|
|
*
|
|
|
|
* Copyright 2013 Zhang Zhaolong <zhangzl2013@126.com>
|
|
|
|
*
|
|
|
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
|
|
* you may not use this file except in compliance with the License.
|
|
|
|
* You may obtain a copy of the License at
|
|
|
|
*
|
|
|
|
* http://www.apache.org/licenses/LICENSE-2.0
|
|
|
|
*
|
|
|
|
* Unless required by applicable law or agreed to in writing, software
|
|
|
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
|
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
|
|
* See the License for the specific language governing permissions and
|
|
|
|
* limitations under the License.
|
|
|
|
*/
|
|
|
|
|
2014-09-13 00:30:57 +04:00
|
|
|
#include <winpr/crt.h>
|
|
|
|
#include <winpr/windows.h>
|
2014-02-27 07:40:21 +04:00
|
|
|
|
2014-09-13 00:30:57 +04:00
|
|
|
#include "wf_client.h"
|
2014-02-27 07:40:21 +04:00
|
|
|
#include "wf_floatbar.h"
|
2021-11-12 13:20:04 +03:00
|
|
|
|
|
|
|
#include "resource/resource.h"
|
2014-02-27 07:40:21 +04:00
|
|
|
#include "wf_gdi.h"
|
2021-04-28 16:00:24 +03:00
|
|
|
#ifdef _MSC_VER
|
2019-11-06 17:24:51 +03:00
|
|
|
#pragma comment(lib, "Msimg32.lib")
|
2021-04-28 16:00:24 +03:00
|
|
|
#endif
|
2014-02-27 07:40:21 +04:00
|
|
|
|
2018-11-16 12:33:29 +03:00
|
|
|
#define TAG CLIENT_TAG("windows.floatbar")
|
|
|
|
|
2014-02-27 08:17:41 +04:00
|
|
|
/* TIMERs */
|
2019-11-06 17:24:51 +03:00
|
|
|
#define TIMER_HIDE 1
|
|
|
|
#define TIMER_ANIMAT_SHOW 2
|
|
|
|
#define TIMER_ANIMAT_HIDE 3
|
2014-02-27 08:17:41 +04:00
|
|
|
|
2014-02-27 07:40:21 +04:00
|
|
|
/* Button Type */
|
2019-11-06 17:24:51 +03:00
|
|
|
#define BUTTON_LOCKPIN 0
|
|
|
|
#define BUTTON_MINIMIZE 1
|
|
|
|
#define BUTTON_RESTORE 2
|
|
|
|
#define BUTTON_CLOSE 3
|
|
|
|
#define BTN_MAX 4
|
2014-02-27 07:40:21 +04:00
|
|
|
|
|
|
|
/* bmp size */
|
2019-11-06 17:24:51 +03:00
|
|
|
#define BACKGROUND_W 576
|
|
|
|
#define BACKGROUND_H 27
|
|
|
|
#define BUTTON_OFFSET 5
|
|
|
|
#define BUTTON_Y 2
|
|
|
|
#define BUTTON_WIDTH 23
|
|
|
|
#define BUTTON_HEIGHT 21
|
|
|
|
#define BUTTON_SPACING 1
|
|
|
|
|
|
|
|
#define LOCK_X (BACKGROUND_H + BUTTON_OFFSET)
|
|
|
|
#define CLOSE_X ((BACKGROUND_W - (BACKGROUND_H + BUTTON_OFFSET)) - BUTTON_WIDTH)
|
|
|
|
#define RESTORE_X (CLOSE_X - (BUTTON_WIDTH + BUTTON_SPACING))
|
|
|
|
#define MINIMIZE_X (RESTORE_X - (BUTTON_WIDTH + BUTTON_SPACING))
|
|
|
|
#define TEXT_X (BACKGROUND_H + ((BUTTON_WIDTH + BUTTON_SPACING) * 3) + 5)
|
2016-06-22 21:58:39 +03:00
|
|
|
|
2022-02-14 16:59:22 +03:00
|
|
|
typedef struct
|
2018-11-16 12:33:29 +03:00
|
|
|
{
|
|
|
|
wfFloatBar* floatbar;
|
2014-02-27 07:40:21 +04:00
|
|
|
int type;
|
|
|
|
int x, y, h, w;
|
|
|
|
int active;
|
|
|
|
HBITMAP bmp;
|
|
|
|
HBITMAP bmp_act;
|
|
|
|
|
|
|
|
/* Lock Specified */
|
|
|
|
HBITMAP locked_bmp;
|
|
|
|
HBITMAP locked_bmp_act;
|
|
|
|
HBITMAP unlocked_bmp;
|
|
|
|
HBITMAP unlocked_bmp_act;
|
2022-02-14 16:59:22 +03:00
|
|
|
} Button;
|
2014-02-27 07:40:21 +04:00
|
|
|
|
2022-02-14 16:59:22 +03:00
|
|
|
struct s_FloatBar
|
2018-11-16 12:33:29 +03:00
|
|
|
{
|
|
|
|
HINSTANCE root_window;
|
|
|
|
DWORD flags;
|
2014-02-27 07:40:21 +04:00
|
|
|
HWND parent;
|
|
|
|
HWND hwnd;
|
|
|
|
RECT rect;
|
|
|
|
LONG width;
|
|
|
|
LONG height;
|
2018-11-16 12:33:29 +03:00
|
|
|
LONG offset;
|
2014-02-27 07:40:21 +04:00
|
|
|
wfContext* wfc;
|
|
|
|
Button* buttons[BTN_MAX];
|
|
|
|
BOOL shown;
|
|
|
|
BOOL locked;
|
2014-02-27 10:30:58 +04:00
|
|
|
HDC hdcmem;
|
2018-11-16 12:33:29 +03:00
|
|
|
RECT textRect;
|
|
|
|
UINT_PTR animating;
|
2014-02-27 07:40:21 +04:00
|
|
|
};
|
|
|
|
|
2018-11-16 12:33:29 +03:00
|
|
|
static BOOL floatbar_kill_timers(wfFloatBar* floatbar)
|
|
|
|
{
|
2019-11-06 17:24:51 +03:00
|
|
|
UINT_PTR timers[] = { TIMER_HIDE, TIMER_ANIMAT_HIDE, TIMER_ANIMAT_SHOW };
|
2018-11-16 12:33:29 +03:00
|
|
|
|
|
|
|
if (!floatbar)
|
|
|
|
return FALSE;
|
|
|
|
|
2024-01-30 12:25:38 +03:00
|
|
|
for (size_t x = 0; x < ARRAYSIZE(timers); x++)
|
2018-11-16 12:33:29 +03:00
|
|
|
KillTimer(floatbar->hwnd, timers[x]);
|
|
|
|
|
|
|
|
floatbar->animating = 0;
|
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
|
|
|
|
static BOOL floatbar_animation(wfFloatBar* const floatbar, const BOOL show)
|
|
|
|
{
|
2019-11-06 17:24:51 +03:00
|
|
|
UINT_PTR timer = show ? TIMER_ANIMAT_SHOW : TIMER_ANIMAT_HIDE;
|
2018-11-16 12:33:29 +03:00
|
|
|
|
|
|
|
if (!floatbar)
|
|
|
|
return FALSE;
|
|
|
|
|
|
|
|
if (floatbar->shown == show)
|
|
|
|
return TRUE;
|
|
|
|
|
|
|
|
if (floatbar->animating == timer)
|
|
|
|
return TRUE;
|
|
|
|
|
|
|
|
floatbar->animating = timer;
|
|
|
|
|
2021-05-28 18:50:09 +03:00
|
|
|
if (SetTimer(floatbar->hwnd, timer, USER_TIMER_MINIMUM, NULL) == 0)
|
2018-11-16 12:33:29 +03:00
|
|
|
{
|
|
|
|
DWORD err = GetLastError();
|
2019-11-06 17:24:51 +03:00
|
|
|
WLog_ERR(TAG, "SetTimer failed with %08" PRIx32, err);
|
2018-11-16 12:33:29 +03:00
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
|
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
|
|
|
|
static BOOL floatbar_trigger_hide(wfFloatBar* floatbar)
|
|
|
|
{
|
|
|
|
if (!floatbar_kill_timers(floatbar))
|
|
|
|
return FALSE;
|
|
|
|
|
|
|
|
if (!floatbar->locked && floatbar->shown)
|
|
|
|
{
|
2021-05-28 18:50:09 +03:00
|
|
|
if (SetTimer(floatbar->hwnd, TIMER_HIDE, 3000, NULL) == 0)
|
2018-11-16 12:33:29 +03:00
|
|
|
{
|
|
|
|
DWORD err = GetLastError();
|
2019-11-06 17:24:51 +03:00
|
|
|
WLog_ERR(TAG, "SetTimer failed with %08" PRIx32, err);
|
2018-11-16 12:33:29 +03:00
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
|
|
|
|
static BOOL floatbar_hide(wfFloatBar* floatbar)
|
|
|
|
{
|
|
|
|
if (!floatbar_kill_timers(floatbar))
|
|
|
|
return FALSE;
|
|
|
|
|
|
|
|
floatbar->offset = floatbar->height - 2;
|
|
|
|
|
2019-11-06 17:24:51 +03:00
|
|
|
if (!MoveWindow(floatbar->hwnd, floatbar->rect.left, -floatbar->offset, floatbar->width,
|
|
|
|
floatbar->height, TRUE))
|
2018-11-16 12:33:29 +03:00
|
|
|
{
|
|
|
|
DWORD err = GetLastError();
|
2019-11-06 17:24:51 +03:00
|
|
|
WLog_ERR(TAG, "MoveWindow failed with %08" PRIx32, err);
|
2018-11-16 12:33:29 +03:00
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
|
|
|
|
floatbar->shown = FALSE;
|
|
|
|
|
|
|
|
if (!floatbar_trigger_hide(floatbar))
|
|
|
|
return FALSE;
|
|
|
|
|
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
|
|
|
|
static BOOL floatbar_show(wfFloatBar* floatbar)
|
|
|
|
{
|
|
|
|
if (!floatbar_kill_timers(floatbar))
|
|
|
|
return FALSE;
|
|
|
|
|
|
|
|
floatbar->offset = 0;
|
|
|
|
|
2019-11-06 17:24:51 +03:00
|
|
|
if (!MoveWindow(floatbar->hwnd, floatbar->rect.left, -floatbar->offset, floatbar->width,
|
|
|
|
floatbar->height, TRUE))
|
2018-11-16 12:33:29 +03:00
|
|
|
{
|
|
|
|
DWORD err = GetLastError();
|
2019-11-06 17:24:51 +03:00
|
|
|
WLog_ERR(TAG, "MoveWindow failed with %08" PRIx32, err);
|
2018-11-16 12:33:29 +03:00
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
|
|
|
|
floatbar->shown = TRUE;
|
|
|
|
|
|
|
|
if (!floatbar_trigger_hide(floatbar))
|
|
|
|
return FALSE;
|
|
|
|
|
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
|
|
|
|
static BOOL button_set_locked(Button* button, BOOL locked)
|
|
|
|
{
|
|
|
|
if (locked)
|
|
|
|
{
|
|
|
|
button->bmp = button->locked_bmp;
|
|
|
|
button->bmp_act = button->locked_bmp_act;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
button->bmp = button->unlocked_bmp;
|
|
|
|
button->bmp_act = button->unlocked_bmp_act;
|
|
|
|
}
|
|
|
|
|
|
|
|
InvalidateRect(button->floatbar->hwnd, NULL, FALSE);
|
|
|
|
UpdateWindow(button->floatbar->hwnd);
|
2018-12-24 09:52:59 +03:00
|
|
|
return TRUE;
|
2018-11-16 12:33:29 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
static BOOL update_locked_state(wfFloatBar* floatbar)
|
2014-02-27 07:40:21 +04:00
|
|
|
{
|
2018-11-16 12:33:29 +03:00
|
|
|
Button* button;
|
|
|
|
|
|
|
|
if (!floatbar)
|
|
|
|
return FALSE;
|
|
|
|
|
|
|
|
button = floatbar->buttons[3];
|
|
|
|
|
|
|
|
if (!button_set_locked(button, floatbar->locked))
|
|
|
|
return FALSE;
|
|
|
|
|
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
|
2019-11-06 17:24:51 +03:00
|
|
|
static int button_hit(Button* const button)
|
2018-11-16 12:33:29 +03:00
|
|
|
{
|
|
|
|
wfFloatBar* const floatbar = button->floatbar;
|
2014-02-27 07:40:21 +04:00
|
|
|
|
|
|
|
switch (button->type)
|
|
|
|
{
|
|
|
|
case BUTTON_LOCKPIN:
|
2018-11-16 12:33:29 +03:00
|
|
|
floatbar->locked = !floatbar->locked;
|
|
|
|
update_locked_state(floatbar);
|
2014-02-27 07:40:21 +04:00
|
|
|
break;
|
|
|
|
|
|
|
|
case BUTTON_MINIMIZE:
|
|
|
|
ShowWindow(floatbar->parent, SW_MINIMIZE);
|
|
|
|
break;
|
|
|
|
|
|
|
|
case BUTTON_RESTORE:
|
|
|
|
wf_toggle_fullscreen(floatbar->wfc);
|
|
|
|
break;
|
|
|
|
|
|
|
|
case BUTTON_CLOSE:
|
2018-11-16 12:33:29 +03:00
|
|
|
SendMessage(floatbar->parent, WM_DESTROY, 0, 0);
|
2014-02-27 07:40:21 +04:00
|
|
|
break;
|
|
|
|
|
|
|
|
default:
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2018-11-16 12:33:29 +03:00
|
|
|
static int button_paint(const Button* const button, const HDC hdc)
|
2014-02-27 07:40:21 +04:00
|
|
|
{
|
2018-11-16 12:33:29 +03:00
|
|
|
if (button != NULL)
|
|
|
|
{
|
|
|
|
wfFloatBar* floatbar = button->floatbar;
|
|
|
|
BLENDFUNCTION bf;
|
|
|
|
SelectObject(floatbar->hdcmem, button->active ? button->bmp_act : button->bmp);
|
|
|
|
bf.BlendOp = AC_SRC_OVER;
|
|
|
|
bf.BlendFlags = 0;
|
|
|
|
bf.SourceConstantAlpha = 255;
|
|
|
|
bf.AlphaFormat = AC_SRC_ALPHA;
|
2019-11-06 17:24:51 +03:00
|
|
|
AlphaBlend(hdc, button->x, button->y, button->w, button->h, floatbar->hdcmem, 0, 0,
|
|
|
|
button->w, button->h, bf);
|
2018-11-16 12:33:29 +03:00
|
|
|
}
|
2016-06-22 21:58:39 +03:00
|
|
|
|
2014-02-27 07:40:21 +04:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2018-11-16 12:33:29 +03:00
|
|
|
static Button* floatbar_create_button(wfFloatBar* const floatbar, const int type, const int resid,
|
2019-11-06 17:24:51 +03:00
|
|
|
const int resid_act, const int x, const int y, const int h,
|
|
|
|
const int w)
|
2014-02-27 07:40:21 +04:00
|
|
|
{
|
2019-11-06 17:24:51 +03:00
|
|
|
Button* button = (Button*)calloc(1, sizeof(Button));
|
2014-02-27 07:40:21 +04:00
|
|
|
|
|
|
|
if (!button)
|
|
|
|
return NULL;
|
|
|
|
|
2014-02-27 08:17:41 +04:00
|
|
|
button->floatbar = floatbar;
|
2014-02-27 07:40:21 +04:00
|
|
|
button->type = type;
|
|
|
|
button->x = x;
|
|
|
|
button->y = y;
|
|
|
|
button->w = w;
|
|
|
|
button->h = h;
|
|
|
|
button->active = FALSE;
|
2018-11-16 12:33:29 +03:00
|
|
|
button->bmp = (HBITMAP)LoadImage(floatbar->root_window, MAKEINTRESOURCE(resid), IMAGE_BITMAP, 0,
|
|
|
|
0, LR_DEFAULTCOLOR);
|
|
|
|
button->bmp_act = (HBITMAP)LoadImage(floatbar->root_window, MAKEINTRESOURCE(resid_act),
|
|
|
|
IMAGE_BITMAP, 0, 0, LR_DEFAULTCOLOR);
|
2014-02-27 07:40:21 +04:00
|
|
|
return button;
|
|
|
|
}
|
|
|
|
|
2018-11-16 12:33:29 +03:00
|
|
|
static Button* floatbar_create_lock_button(wfFloatBar* const floatbar, const int unlock_resid,
|
2019-11-06 17:24:51 +03:00
|
|
|
const int unlock_resid_act, const int lock_resid,
|
|
|
|
const int lock_resid_act, const int x, const int y,
|
|
|
|
const int h, const int w)
|
2014-02-27 07:40:21 +04:00
|
|
|
{
|
2019-11-06 17:24:51 +03:00
|
|
|
Button* button = floatbar_create_button(floatbar, BUTTON_LOCKPIN, unlock_resid,
|
|
|
|
unlock_resid_act, x, y, h, w);
|
2014-02-27 07:40:21 +04:00
|
|
|
|
|
|
|
if (!button)
|
|
|
|
return NULL;
|
|
|
|
|
|
|
|
button->unlocked_bmp = button->bmp;
|
|
|
|
button->unlocked_bmp_act = button->bmp_act;
|
2018-11-16 12:33:29 +03:00
|
|
|
button->locked_bmp = (HBITMAP)LoadImage(floatbar->wfc->hInstance, MAKEINTRESOURCE(lock_resid),
|
|
|
|
IMAGE_BITMAP, 0, 0, LR_DEFAULTCOLOR);
|
2019-11-06 17:24:51 +03:00
|
|
|
button->locked_bmp_act =
|
|
|
|
(HBITMAP)LoadImage(floatbar->wfc->hInstance, MAKEINTRESOURCE(lock_resid_act), IMAGE_BITMAP,
|
|
|
|
0, 0, LR_DEFAULTCOLOR);
|
2014-02-27 07:40:21 +04:00
|
|
|
return button;
|
|
|
|
}
|
|
|
|
|
2018-11-16 12:33:29 +03:00
|
|
|
static Button* floatbar_get_button(const wfFloatBar* const floatbar, const int x, const int y)
|
2014-02-27 07:40:21 +04:00
|
|
|
{
|
2018-11-16 12:33:29 +03:00
|
|
|
if ((y > BUTTON_Y) && (y < BUTTON_Y + BUTTON_HEIGHT))
|
|
|
|
{
|
2024-01-30 12:25:38 +03:00
|
|
|
for (int i = 0; i < BTN_MAX; i++)
|
2018-11-16 12:33:29 +03:00
|
|
|
{
|
|
|
|
if ((floatbar->buttons[i] != NULL) && (x > floatbar->buttons[i]->x) &&
|
|
|
|
(x < floatbar->buttons[i]->x + floatbar->buttons[i]->w))
|
|
|
|
{
|
2014-02-27 07:40:21 +04:00
|
|
|
return floatbar->buttons[i];
|
2018-11-16 12:33:29 +03:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2014-02-27 07:40:21 +04:00
|
|
|
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
2018-11-16 12:33:29 +03:00
|
|
|
static BOOL floatbar_paint(wfFloatBar* const floatbar, const HDC hdc)
|
2014-02-27 07:40:21 +04:00
|
|
|
{
|
2018-11-16 12:33:29 +03:00
|
|
|
HPEN hpen;
|
|
|
|
HGDIOBJECT orig;
|
2014-02-27 07:40:21 +04:00
|
|
|
/* paint background */
|
2018-11-16 12:33:29 +03:00
|
|
|
GRADIENT_RECT gradientRect = { 0, 1 };
|
|
|
|
COLORREF rgbTop = RGB(117, 154, 198);
|
|
|
|
COLORREF rgbBottom = RGB(6, 55, 120);
|
|
|
|
const int top = 0;
|
|
|
|
int left = 0;
|
|
|
|
int bottom = BACKGROUND_H - 1;
|
|
|
|
int right = BACKGROUND_W - 1;
|
|
|
|
const int angleOffset = BACKGROUND_H - 1;
|
2021-04-28 16:02:54 +03:00
|
|
|
TRIVERTEX triVertext[2] = { { left, top, GetRValue(rgbTop) << 8, GetGValue(rgbTop) << 8,
|
|
|
|
GetBValue(rgbTop) << 8, 0x0000 },
|
|
|
|
{ right, bottom, GetRValue(rgbBottom) << 8,
|
|
|
|
GetGValue(rgbBottom) << 8, GetBValue(rgbBottom) << 8, 0x0000 } };
|
2018-11-16 12:33:29 +03:00
|
|
|
|
|
|
|
if (!floatbar)
|
|
|
|
return FALSE;
|
|
|
|
|
|
|
|
GradientFill(hdc, triVertext, 2, &gradientRect, 1, GRADIENT_FILL_RECT_V);
|
|
|
|
/* paint shadow */
|
|
|
|
hpen = CreatePen(PS_SOLID, 1, RGB(71, 71, 71));
|
|
|
|
orig = SelectObject(hdc, hpen);
|
|
|
|
MoveToEx(hdc, left, top, NULL);
|
|
|
|
LineTo(hdc, left + angleOffset, bottom);
|
|
|
|
LineTo(hdc, right - angleOffset, bottom);
|
|
|
|
LineTo(hdc, right + 1, top - 1);
|
|
|
|
DeleteObject(hpen);
|
|
|
|
hpen = CreatePen(PS_SOLID, 1, RGB(107, 141, 184));
|
|
|
|
SelectObject(hdc, hpen);
|
|
|
|
left += 1;
|
|
|
|
bottom -= 1;
|
|
|
|
right -= 1;
|
|
|
|
MoveToEx(hdc, left, top, NULL);
|
|
|
|
LineTo(hdc, left + (angleOffset - 1), bottom);
|
|
|
|
LineTo(hdc, right - (angleOffset - 1), bottom);
|
|
|
|
LineTo(hdc, right + 1, top - 1);
|
|
|
|
DeleteObject(hpen);
|
|
|
|
SelectObject(hdc, orig);
|
2019-11-06 17:24:51 +03:00
|
|
|
DrawText(hdc, floatbar->wfc->window_title, wcslen(floatbar->wfc->window_title),
|
|
|
|
&floatbar->textRect,
|
2018-11-16 12:33:29 +03:00
|
|
|
DT_CENTER | DT_VCENTER | DT_END_ELLIPSIS | DT_NOPREFIX | DT_SINGLELINE);
|
2014-02-27 07:40:21 +04:00
|
|
|
|
|
|
|
/* paint buttons */
|
2016-06-22 21:58:39 +03:00
|
|
|
|
2024-01-30 12:25:38 +03:00
|
|
|
for (int i = 0; i < BTN_MAX; i++)
|
2014-02-27 10:30:58 +04:00
|
|
|
button_paint(floatbar->buttons[i], hdc);
|
2014-02-27 07:40:21 +04:00
|
|
|
|
2018-11-16 12:33:29 +03:00
|
|
|
return TRUE;
|
2014-02-27 07:40:21 +04:00
|
|
|
}
|
|
|
|
|
2018-11-16 12:33:29 +03:00
|
|
|
static LRESULT CALLBACK floatbar_proc(const HWND hWnd, const UINT Msg, const WPARAM wParam,
|
|
|
|
const LPARAM lParam)
|
2014-02-27 07:40:21 +04:00
|
|
|
{
|
|
|
|
static int dragging = FALSE;
|
|
|
|
static int lbtn_dwn = FALSE;
|
|
|
|
static int btn_dwn_x = 0;
|
2018-11-16 12:33:29 +03:00
|
|
|
static wfFloatBar* floatbar;
|
2014-02-27 09:44:49 +04:00
|
|
|
static TRACKMOUSEEVENT tme;
|
|
|
|
PAINTSTRUCT ps;
|
2014-02-27 07:40:21 +04:00
|
|
|
Button* button;
|
2014-02-27 10:30:58 +04:00
|
|
|
HDC hdc;
|
2014-02-27 07:40:21 +04:00
|
|
|
int pos_x;
|
|
|
|
int pos_y;
|
2016-06-22 21:58:39 +03:00
|
|
|
NONCLIENTMETRICS ncm;
|
2014-02-27 09:44:49 +04:00
|
|
|
int xScreen = GetSystemMetrics(SM_CXSCREEN);
|
2014-02-27 07:40:21 +04:00
|
|
|
|
2018-11-16 12:33:29 +03:00
|
|
|
switch (Msg)
|
2014-02-27 07:40:21 +04:00
|
|
|
{
|
|
|
|
case WM_CREATE:
|
2019-11-06 17:24:51 +03:00
|
|
|
floatbar = ((wfFloatBar*)((CREATESTRUCT*)lParam)->lpCreateParams);
|
2014-02-27 07:40:21 +04:00
|
|
|
floatbar->hwnd = hWnd;
|
|
|
|
GetWindowRect(floatbar->hwnd, &floatbar->rect);
|
|
|
|
floatbar->width = floatbar->rect.right - floatbar->rect.left;
|
|
|
|
floatbar->height = floatbar->rect.bottom - floatbar->rect.top;
|
2014-02-27 10:30:58 +04:00
|
|
|
hdc = GetDC(hWnd);
|
|
|
|
floatbar->hdcmem = CreateCompatibleDC(hdc);
|
|
|
|
ReleaseDC(hWnd, hdc);
|
2014-02-27 09:44:49 +04:00
|
|
|
tme.cbSize = sizeof(TRACKMOUSEEVENT);
|
|
|
|
tme.dwFlags = TME_LEAVE;
|
|
|
|
tme.hwndTrack = hWnd;
|
|
|
|
tme.dwHoverTime = HOVER_DEFAULT;
|
2018-11-16 12:33:29 +03:00
|
|
|
// Use caption font, white, draw transparent
|
|
|
|
GetClientRect(hWnd, &floatbar->textRect);
|
|
|
|
InflateRect(&floatbar->textRect, -TEXT_X, 0);
|
|
|
|
SetBkMode(hdc, TRANSPARENT);
|
|
|
|
SetTextColor(hdc, RGB(255, 255, 255));
|
|
|
|
ncm.cbSize = sizeof(NONCLIENTMETRICS);
|
|
|
|
SystemParametersInfo(SPI_GETNONCLIENTMETRICS, sizeof(NONCLIENTMETRICS), &ncm, 0);
|
|
|
|
SelectObject(hdc, CreateFontIndirect(&ncm.lfCaptionFont));
|
|
|
|
floatbar_trigger_hide(floatbar);
|
2014-02-27 07:40:21 +04:00
|
|
|
break;
|
|
|
|
|
|
|
|
case WM_PAINT:
|
2014-02-27 10:30:58 +04:00
|
|
|
hdc = BeginPaint(hWnd, &ps);
|
|
|
|
floatbar_paint(floatbar, hdc);
|
2014-02-27 07:40:21 +04:00
|
|
|
EndPaint(hWnd, &ps);
|
|
|
|
break;
|
|
|
|
|
|
|
|
case WM_LBUTTONDOWN:
|
|
|
|
pos_x = lParam & 0xffff;
|
|
|
|
pos_y = (lParam >> 16) & 0xffff;
|
2016-06-22 21:58:39 +03:00
|
|
|
button = floatbar_get_button(floatbar, pos_x, pos_y);
|
2018-11-16 12:33:29 +03:00
|
|
|
|
2014-02-27 07:40:21 +04:00
|
|
|
if (!button)
|
|
|
|
{
|
|
|
|
SetCapture(hWnd);
|
|
|
|
dragging = TRUE;
|
|
|
|
btn_dwn_x = lParam & 0xffff;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
lbtn_dwn = TRUE;
|
|
|
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
case WM_LBUTTONUP:
|
|
|
|
pos_x = lParam & 0xffff;
|
|
|
|
pos_y = (lParam >> 16) & 0xffff;
|
|
|
|
ReleaseCapture();
|
|
|
|
dragging = FALSE;
|
|
|
|
|
|
|
|
if (lbtn_dwn)
|
|
|
|
{
|
2014-02-27 08:17:41 +04:00
|
|
|
button = floatbar_get_button(floatbar, pos_x, pos_y);
|
2018-11-16 12:33:29 +03:00
|
|
|
|
2014-02-27 07:40:21 +04:00
|
|
|
if (button)
|
|
|
|
button_hit(button);
|
2018-11-16 12:33:29 +03:00
|
|
|
|
2014-02-27 07:40:21 +04:00
|
|
|
lbtn_dwn = FALSE;
|
|
|
|
}
|
2018-11-16 12:33:29 +03:00
|
|
|
|
2014-02-27 07:40:21 +04:00
|
|
|
break;
|
|
|
|
|
|
|
|
case WM_MOUSEMOVE:
|
|
|
|
pos_x = lParam & 0xffff;
|
|
|
|
pos_y = (lParam >> 16) & 0xffff;
|
|
|
|
|
2018-11-16 12:33:29 +03:00
|
|
|
if (!floatbar->locked)
|
2014-02-27 09:44:49 +04:00
|
|
|
floatbar_animation(floatbar, TRUE);
|
2014-02-27 07:40:21 +04:00
|
|
|
|
|
|
|
if (dragging)
|
|
|
|
{
|
2014-02-27 09:44:49 +04:00
|
|
|
floatbar->rect.left = floatbar->rect.left + (lParam & 0xffff) - btn_dwn_x;
|
2014-02-27 07:40:21 +04:00
|
|
|
|
2014-02-27 09:44:49 +04:00
|
|
|
if (floatbar->rect.left < 0)
|
|
|
|
floatbar->rect.left = 0;
|
|
|
|
else if (floatbar->rect.left > xScreen - floatbar->width)
|
|
|
|
floatbar->rect.left = xScreen - floatbar->width;
|
2014-02-27 07:40:21 +04:00
|
|
|
|
2018-11-16 12:33:29 +03:00
|
|
|
MoveWindow(hWnd, floatbar->rect.left, 0, floatbar->width, floatbar->height, TRUE);
|
2014-02-27 07:40:21 +04:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2024-01-30 12:25:38 +03:00
|
|
|
for (int i = 0; i < BTN_MAX; i++)
|
2018-11-16 12:33:29 +03:00
|
|
|
{
|
|
|
|
if (floatbar->buttons[i] != NULL)
|
|
|
|
{
|
|
|
|
floatbar->buttons[i]->active = FALSE;
|
|
|
|
}
|
|
|
|
}
|
2014-02-27 07:40:21 +04:00
|
|
|
|
2014-02-27 08:17:41 +04:00
|
|
|
button = floatbar_get_button(floatbar, pos_x, pos_y);
|
2018-11-16 12:33:29 +03:00
|
|
|
|
2014-02-27 07:40:21 +04:00
|
|
|
if (button)
|
|
|
|
button->active = TRUE;
|
|
|
|
|
|
|
|
InvalidateRect(hWnd, NULL, FALSE);
|
|
|
|
UpdateWindow(hWnd);
|
|
|
|
}
|
|
|
|
|
|
|
|
TrackMouseEvent(&tme);
|
|
|
|
break;
|
|
|
|
|
|
|
|
case WM_CAPTURECHANGED:
|
|
|
|
dragging = FALSE;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case WM_MOUSELEAVE:
|
2019-11-06 17:24:51 +03:00
|
|
|
{
|
2024-01-30 12:25:38 +03:00
|
|
|
for (int i = 0; i < BTN_MAX; i++)
|
2019-11-06 17:24:51 +03:00
|
|
|
{
|
|
|
|
if (floatbar->buttons[i] != NULL)
|
2018-11-16 12:33:29 +03:00
|
|
|
{
|
2019-11-06 17:24:51 +03:00
|
|
|
floatbar->buttons[i]->active = FALSE;
|
2018-11-16 12:33:29 +03:00
|
|
|
}
|
|
|
|
}
|
2014-02-27 07:40:21 +04:00
|
|
|
|
2019-11-06 17:24:51 +03:00
|
|
|
InvalidateRect(hWnd, NULL, FALSE);
|
|
|
|
UpdateWindow(hWnd);
|
|
|
|
floatbar_trigger_hide(floatbar);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
2014-02-27 07:40:21 +04:00
|
|
|
case WM_TIMER:
|
|
|
|
switch (wParam)
|
|
|
|
{
|
|
|
|
case TIMER_HIDE:
|
2018-11-16 12:33:29 +03:00
|
|
|
floatbar_animation(floatbar, FALSE);
|
2016-06-22 21:58:39 +03:00
|
|
|
break;
|
2016-08-03 13:09:24 +03:00
|
|
|
|
2018-11-16 12:33:29 +03:00
|
|
|
case TIMER_ANIMAT_SHOW:
|
2019-11-06 17:24:51 +03:00
|
|
|
{
|
|
|
|
floatbar->offset--;
|
|
|
|
MoveWindow(floatbar->hwnd, floatbar->rect.left, -floatbar->offset,
|
|
|
|
floatbar->width, floatbar->height, TRUE);
|
2018-11-16 12:33:29 +03:00
|
|
|
|
2019-11-06 17:24:51 +03:00
|
|
|
if (floatbar->offset <= 0)
|
|
|
|
floatbar_show(floatbar);
|
2018-11-16 12:33:29 +03:00
|
|
|
|
2019-11-06 17:24:51 +03:00
|
|
|
break;
|
|
|
|
}
|
2016-08-03 13:09:24 +03:00
|
|
|
|
2018-11-16 12:33:29 +03:00
|
|
|
case TIMER_ANIMAT_HIDE:
|
2019-11-06 17:24:51 +03:00
|
|
|
{
|
|
|
|
floatbar->offset++;
|
|
|
|
MoveWindow(floatbar->hwnd, floatbar->rect.left, -floatbar->offset,
|
|
|
|
floatbar->width, floatbar->height, TRUE);
|
2018-11-16 12:33:29 +03:00
|
|
|
|
2019-11-06 17:24:51 +03:00
|
|
|
if (floatbar->offset >= floatbar->height - 2)
|
|
|
|
floatbar_hide(floatbar);
|
2018-11-16 12:33:29 +03:00
|
|
|
|
2019-11-06 17:24:51 +03:00
|
|
|
break;
|
|
|
|
}
|
2018-11-16 12:33:29 +03:00
|
|
|
|
2014-02-27 07:40:21 +04:00
|
|
|
default:
|
|
|
|
break;
|
|
|
|
}
|
2018-11-16 12:33:29 +03:00
|
|
|
|
2014-02-27 07:40:21 +04:00
|
|
|
break;
|
2014-02-27 10:30:58 +04:00
|
|
|
|
2014-02-27 07:40:21 +04:00
|
|
|
case WM_DESTROY:
|
2014-02-27 10:30:58 +04:00
|
|
|
DeleteDC(floatbar->hdcmem);
|
2014-02-27 07:40:21 +04:00
|
|
|
PostQuitMessage(0);
|
|
|
|
break;
|
|
|
|
|
|
|
|
default:
|
|
|
|
return DefWindowProc(hWnd, Msg, wParam, lParam);
|
|
|
|
}
|
2014-02-27 08:17:41 +04:00
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2018-11-16 12:33:29 +03:00
|
|
|
static BOOL floatbar_window_create(wfFloatBar* floatbar)
|
2014-02-27 07:40:21 +04:00
|
|
|
{
|
|
|
|
WNDCLASSEX wnd_cls;
|
|
|
|
HWND barWnd;
|
2016-06-22 21:58:39 +03:00
|
|
|
HRGN hRgn;
|
|
|
|
POINT pt[4];
|
2018-11-16 12:33:29 +03:00
|
|
|
RECT rect;
|
|
|
|
LONG x;
|
|
|
|
|
|
|
|
if (!floatbar)
|
|
|
|
return FALSE;
|
|
|
|
|
|
|
|
if (!GetWindowRect(floatbar->parent, &rect))
|
|
|
|
return FALSE;
|
2016-06-22 21:58:39 +03:00
|
|
|
|
2018-11-16 12:33:29 +03:00
|
|
|
x = (rect.right - rect.left - BACKGROUND_W) / 2;
|
2019-11-06 17:24:51 +03:00
|
|
|
wnd_cls.cbSize = sizeof(WNDCLASSEX);
|
|
|
|
wnd_cls.style = CS_HREDRAW | CS_VREDRAW | CS_OWNDC;
|
|
|
|
wnd_cls.lpfnWndProc = floatbar_proc;
|
|
|
|
wnd_cls.cbClsExtra = 0;
|
|
|
|
wnd_cls.cbWndExtra = 0;
|
|
|
|
wnd_cls.hIcon = LoadIcon(NULL, IDI_APPLICATION);
|
|
|
|
wnd_cls.hCursor = LoadCursor(floatbar->root_window, IDC_ARROW);
|
2014-02-27 07:40:21 +04:00
|
|
|
wnd_cls.hbrBackground = NULL;
|
2019-11-06 17:24:51 +03:00
|
|
|
wnd_cls.lpszMenuName = NULL;
|
2014-02-27 08:17:41 +04:00
|
|
|
wnd_cls.lpszClassName = L"floatbar";
|
2019-11-06 17:24:51 +03:00
|
|
|
wnd_cls.hInstance = floatbar->root_window;
|
|
|
|
wnd_cls.hIconSm = LoadIcon(NULL, IDI_APPLICATION);
|
2014-02-27 07:40:21 +04:00
|
|
|
RegisterClassEx(&wnd_cls);
|
2019-11-06 17:24:51 +03:00
|
|
|
barWnd = CreateWindowEx(WS_EX_TOPMOST, L"floatbar", L"floatbar", WS_CHILD, x, 0, BACKGROUND_W,
|
|
|
|
BACKGROUND_H, floatbar->parent, NULL, floatbar->root_window, floatbar);
|
2014-02-27 07:40:21 +04:00
|
|
|
|
|
|
|
if (barWnd == NULL)
|
2018-11-16 12:33:29 +03:00
|
|
|
return FALSE;
|
2016-08-03 13:09:24 +03:00
|
|
|
|
2016-06-22 21:58:39 +03:00
|
|
|
pt[0].x = 0;
|
|
|
|
pt[0].y = 0;
|
|
|
|
pt[1].x = BACKGROUND_W;
|
|
|
|
pt[1].y = 0;
|
|
|
|
pt[2].x = BACKGROUND_W - BACKGROUND_H;
|
|
|
|
pt[2].y = BACKGROUND_H;
|
|
|
|
pt[3].x = BACKGROUND_H;
|
|
|
|
pt[3].y = BACKGROUND_H;
|
2018-11-16 12:33:29 +03:00
|
|
|
hRgn = CreatePolygonRgn(pt, 4, ALTERNATE);
|
|
|
|
SetWindowRgn(barWnd, hRgn, TRUE);
|
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
|
|
|
|
void wf_floatbar_free(wfFloatBar* floatbar)
|
|
|
|
{
|
|
|
|
if (!floatbar)
|
|
|
|
return;
|
|
|
|
|
|
|
|
free(floatbar);
|
|
|
|
}
|
|
|
|
|
|
|
|
wfFloatBar* wf_floatbar_new(wfContext* wfc, HINSTANCE window, DWORD flags)
|
|
|
|
{
|
|
|
|
wfFloatBar* floatbar;
|
|
|
|
|
|
|
|
/* Floatbar not enabled */
|
|
|
|
if ((flags & 0x0001) == 0)
|
|
|
|
return NULL;
|
|
|
|
|
|
|
|
if (!wfc)
|
|
|
|
return NULL;
|
|
|
|
|
|
|
|
// TODO: Disable for remote app
|
2019-11-06 17:24:51 +03:00
|
|
|
floatbar = (wfFloatBar*)calloc(1, sizeof(wfFloatBar));
|
2018-11-16 12:33:29 +03:00
|
|
|
|
|
|
|
if (!floatbar)
|
|
|
|
return NULL;
|
2016-06-22 21:58:39 +03:00
|
|
|
|
2018-11-16 12:33:29 +03:00
|
|
|
floatbar->root_window = window;
|
|
|
|
floatbar->flags = flags;
|
|
|
|
floatbar->wfc = wfc;
|
|
|
|
floatbar->locked = (flags & 0x0002) != 0;
|
|
|
|
floatbar->shown = (flags & 0x0006) != 0; /* If it is loked or shown show it */
|
|
|
|
floatbar->hwnd = NULL;
|
|
|
|
floatbar->parent = wfc->hwnd;
|
|
|
|
floatbar->hdcmem = NULL;
|
|
|
|
|
|
|
|
if (wfc->fullscreen_toggle)
|
|
|
|
{
|
2019-11-06 17:24:51 +03:00
|
|
|
floatbar->buttons[0] =
|
|
|
|
floatbar_create_button(floatbar, BUTTON_MINIMIZE, IDB_MINIMIZE, IDB_MINIMIZE_ACT,
|
|
|
|
MINIMIZE_X, BUTTON_Y, BUTTON_HEIGHT, BUTTON_WIDTH);
|
|
|
|
floatbar->buttons[1] =
|
|
|
|
floatbar_create_button(floatbar, BUTTON_RESTORE, IDB_RESTORE, IDB_RESTORE_ACT,
|
|
|
|
RESTORE_X, BUTTON_Y, BUTTON_HEIGHT, BUTTON_WIDTH);
|
2018-11-16 12:33:29 +03:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
floatbar->buttons[0] = NULL;
|
|
|
|
floatbar->buttons[1] = NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
floatbar->buttons[2] = floatbar_create_button(floatbar, BUTTON_CLOSE, IDB_CLOSE, IDB_CLOSE_ACT,
|
2019-11-06 17:24:51 +03:00
|
|
|
CLOSE_X, BUTTON_Y, BUTTON_HEIGHT, BUTTON_WIDTH);
|
|
|
|
floatbar->buttons[3] =
|
|
|
|
floatbar_create_lock_button(floatbar, IDB_UNLOCK, IDB_UNLOCK_ACT, IDB_LOCK, IDB_LOCK_ACT,
|
|
|
|
LOCK_X, BUTTON_Y, BUTTON_HEIGHT, BUTTON_WIDTH);
|
2018-11-16 12:33:29 +03:00
|
|
|
|
|
|
|
if (!floatbar_window_create(floatbar))
|
|
|
|
goto fail;
|
|
|
|
|
|
|
|
if (!update_locked_state(floatbar))
|
|
|
|
goto fail;
|
|
|
|
|
2023-10-13 10:48:44 +03:00
|
|
|
if (!wf_floatbar_toggle_fullscreen(
|
|
|
|
floatbar, freerdp_settings_get_bool(wfc->common.context.settings, FreeRDP_Fullscreen)))
|
2018-11-16 12:33:29 +03:00
|
|
|
goto fail;
|
|
|
|
|
|
|
|
return floatbar;
|
|
|
|
fail:
|
|
|
|
wf_floatbar_free(floatbar);
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
BOOL wf_floatbar_toggle_fullscreen(wfFloatBar* floatbar, BOOL fullscreen)
|
|
|
|
{
|
|
|
|
BOOL show_fs, show_wn;
|
|
|
|
|
|
|
|
if (!floatbar)
|
|
|
|
return FALSE;
|
|
|
|
|
|
|
|
show_fs = (floatbar->flags & 0x0010) != 0;
|
|
|
|
show_wn = (floatbar->flags & 0x0020) != 0;
|
|
|
|
|
|
|
|
if ((show_fs && fullscreen) || (show_wn && !fullscreen))
|
|
|
|
{
|
|
|
|
ShowWindow(floatbar->hwnd, SW_SHOWNORMAL);
|
|
|
|
Sleep(10);
|
|
|
|
|
|
|
|
if (floatbar->shown)
|
|
|
|
floatbar_show(floatbar);
|
|
|
|
else
|
|
|
|
floatbar_hide(floatbar);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
ShowWindow(floatbar->hwnd, SW_HIDE);
|
|
|
|
}
|
2016-06-22 21:58:39 +03:00
|
|
|
|
2018-11-16 12:33:29 +03:00
|
|
|
return TRUE;
|
2014-02-27 07:40:21 +04:00
|
|
|
}
|