Blame client/Windows/wf_floatbar.c

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