mirror of
https://github.com/WinampDesktop/winamp.git
synced 2024-12-24 06:04:50 +01:00
1113 lines
28 KiB
C++
1113 lines
28 KiB
C++
#include "precomp.h"
|
|
#include "appbarwnd.h"
|
|
#include <tataki/region/region.h>
|
|
#include <api/wnd/resizable.h>
|
|
#include <api/wndmgr/layout.h>
|
|
#include <api/config/items/cfgitem.h>
|
|
#include <api/config/items/attrint.h>
|
|
#include "../../../../Plugins/General/gen_ff/wa2cfgitems.h"
|
|
|
|
#define CB_CHECK 0x101
|
|
#define DOCK_DISTANCE_X 5
|
|
#define DOCK_DISTANCE_Y 5
|
|
|
|
#ifndef WIN32
|
|
#error port me or remove me from the inheritance on this platform !
|
|
#endif
|
|
|
|
#include <windows.h>
|
|
#include <windowsx.h>
|
|
#include <shlobj.h>
|
|
#include "../../../../Plugins/General/gen_ff/main.h"
|
|
#include "appbarwnd.h"
|
|
|
|
extern _int cfg_options_appbardockingdistance;
|
|
|
|
// -----------------------------------------------------------------------
|
|
AppBarWnd::AppBarWnd() {
|
|
m_registered = 0;
|
|
m_side = APPBAR_NOTDOCKED;
|
|
m_enabled = 0;
|
|
m_cur_side = APPBAR_NOTDOCKED;
|
|
m_cur_autohide = 0;
|
|
m_cur_hiding = 0;
|
|
m_oldZOrder = NULL;
|
|
m_destroying = FALSE;
|
|
m_norestore = 0;
|
|
m_sliding = 0;
|
|
m_autounhide_timer_set = 0;
|
|
m_autohide_timer_set = 0;
|
|
m_suspended = 0;
|
|
m_fs = 0;
|
|
m_wahidden = 0;
|
|
}
|
|
|
|
// -----------------------------------------------------------------------
|
|
AppBarWnd::~AppBarWnd() {
|
|
m_destroying = TRUE;
|
|
if (m_cur_side != APPBAR_NOTDOCKED) unDock();
|
|
unregisterWinAppBar();
|
|
}
|
|
|
|
// -----------------------------------------------------------------------
|
|
int AppBarWnd::registerWinAppBar()
|
|
{
|
|
if (m_registered)
|
|
unregisterWinAppBar();
|
|
|
|
APPBARDATA abd;
|
|
|
|
abd.cbSize = sizeof(APPBARDATA);
|
|
abd.hWnd = getOsWindowHandle();
|
|
abd.uCallbackMessage = APPBAR_CALLBACK;
|
|
|
|
m_registered = (int)SHAppBarMessage(ABM_NEW, &abd);
|
|
return m_registered;
|
|
}
|
|
|
|
// -----------------------------------------------------------------------
|
|
void AppBarWnd::unregisterWinAppBar() {
|
|
if (m_registered) {
|
|
APPBARDATA abd;
|
|
|
|
abd.cbSize = sizeof(APPBARDATA);
|
|
abd.hWnd = getOsWindowHandle();
|
|
|
|
SHAppBarMessage(ABM_REMOVE, &abd);
|
|
m_registered = 0;
|
|
}
|
|
}
|
|
|
|
// -----------------------------------------------------------------------
|
|
void AppBarWnd::appbar_dock(int side) {
|
|
m_side = side;
|
|
updateDocking();
|
|
}
|
|
|
|
// -----------------------------------------------------------------------
|
|
int AppBarWnd::appbar_isDocked() {
|
|
return m_side != APPBAR_NOTDOCKED;
|
|
}
|
|
|
|
// -----------------------------------------------------------------------
|
|
int AppBarWnd::appbar_getSide() {
|
|
return m_side;
|
|
}
|
|
|
|
// -----------------------------------------------------------------------
|
|
void AppBarWnd::appbar_setEnabledSides(int mask) {
|
|
m_enabled = mask;
|
|
}
|
|
|
|
// -----------------------------------------------------------------------
|
|
int AppBarWnd::appbar_getEnabledSides() {
|
|
return m_enabled;
|
|
}
|
|
|
|
// -----------------------------------------------------------------------
|
|
int AppBarWnd::appbar_isSideEnabled(int side) {
|
|
if (side == APPBAR_LEFT && !(m_enabled & APPBAR_LEFT_ENABLED)) return 0;
|
|
if (side == APPBAR_TOP && !(m_enabled & APPBAR_TOP_ENABLED)) return 0;
|
|
if (side == APPBAR_RIGHT && !(m_enabled & APPBAR_RIGHT_ENABLED)) return 0;
|
|
if (side == APPBAR_BOTTOM && !(m_enabled & APPBAR_BOTTOM_ENABLED)) return 0;
|
|
return 1;
|
|
}
|
|
|
|
// -----------------------------------------------------------------------
|
|
int AppBarWnd::appbar_isSideAutoHideSafe(int side) {
|
|
OSWINDOWHANDLE cur = getCurAutoHide(side);
|
|
|
|
if (cur == NULL || cur == getOsWindowHandle()) {
|
|
RECT primary = {0};
|
|
Wasabi::Std::getViewport(&primary, hwnd, 1);
|
|
|
|
DebugStringW( L"primary screen coords = %d,%d -> %d,%d (%dx%d)\n", primary.left, primary.top, primary.right, primary.bottom, primary.right - primary.left, primary.bottom - primary.top );
|
|
int monitor = 0;
|
|
//int g = 0;
|
|
while (1) {
|
|
RECT r;
|
|
int ret = Wasabi::Std::enumViewports(monitor++, &r, 1);
|
|
if (ret == 0) break;
|
|
|
|
if (Wasabi::Std::rectEqual(&primary, &r)) continue;
|
|
|
|
DebugStringW(L"secondary screen = %d,%d -> %d,%d (%dx%d)\n", r.left, r.top, r.right, r.bottom, r.right-r.left, r.bottom-r.top);
|
|
if (r.right <= primary.left && side == APPBAR_LEFT) return 0;
|
|
if (r.bottom <= primary.top && side == APPBAR_TOP) return 0;
|
|
if (r.left >= primary.right && side == APPBAR_RIGHT) return 0;
|
|
if (r.top >= primary.bottom && side == APPBAR_BOTTOM) return 0;
|
|
}
|
|
}
|
|
else
|
|
return 0;
|
|
|
|
return 1;
|
|
}
|
|
|
|
// -----------------------------------------------------------------------
|
|
OSWINDOWHANDLE AppBarWnd::getCurAutoHide(int side) {
|
|
APPBARDATA abd;
|
|
abd.cbSize = sizeof(APPBARDATA);
|
|
abd.hWnd = getOsWindowHandle();
|
|
abd.uEdge = side;
|
|
return (OSWINDOWHANDLE)SHAppBarMessage(ABM_GETAUTOHIDEBAR, &abd);
|
|
}
|
|
|
|
// -----------------------------------------------------------------------
|
|
int AppBarWnd::appbar_testDock(int x, int y, RECT *dockrect) {
|
|
POINT ptCursor = {x, y};
|
|
LONG cxScreen, cyScreen;
|
|
int dx=999999, dy=999999;
|
|
int horiz=-1, vert=-1;
|
|
RECT viewRect = {0};
|
|
|
|
Wasabi::Std::getViewport(&viewRect, hwnd, 1);
|
|
|
|
// Find out which edge of the screen we're closest to
|
|
cxScreen = viewRect.right;
|
|
cyScreen = viewRect.bottom;
|
|
|
|
if (x < viewRect.left || x > cxScreen || y < viewRect.top || y > cyScreen) return APPBAR_NOTDOCKED;
|
|
|
|
if (ptCursor.x < (cxScreen / 2)) {
|
|
if (m_enabled & APPBAR_LEFT_ENABLED) {
|
|
dx = ptCursor.x;
|
|
horiz = APPBAR_LEFT;
|
|
}
|
|
}
|
|
else {
|
|
if (m_enabled & APPBAR_RIGHT_ENABLED) {
|
|
dx = cxScreen - ptCursor.x;
|
|
horiz = APPBAR_RIGHT;
|
|
}
|
|
}
|
|
|
|
if (ptCursor.y < (cyScreen / 2)) {
|
|
if (m_enabled & APPBAR_TOP_ENABLED) {
|
|
dy = ptCursor.y;
|
|
vert = APPBAR_TOP;
|
|
}
|
|
}
|
|
else {
|
|
if (m_enabled & APPBAR_BOTTOM_ENABLED) {
|
|
dy = cyScreen - ptCursor.y;
|
|
vert = APPBAR_BOTTOM;
|
|
}
|
|
}
|
|
|
|
int ret = -1;
|
|
#ifdef GEN_FF
|
|
int dockdist = cfg_options_appbardockingdistance;
|
|
#else
|
|
// TODO: do a config lookup, but make it not so slow
|
|
/*
|
|
const GUID options_guid =
|
|
{ 0x280876cf, 0x48c0, 0x40bc, { 0x8e, 0x86, 0x73, 0xce, 0x6b, 0xb4, 0x62, 0xe5 } };
|
|
int dockdist = _intVal(WASABI_API_CONFIG->config_getCfgItemByGuid(options_guid), L"Appbars Docking Distance", 5);*/
|
|
int dockdist = 5;
|
|
#endif
|
|
if ((cxScreen * dy) > (cyScreen * dx))
|
|
if (dx <= dockdist)
|
|
ret = horiz;
|
|
if (dy <= dockdist)
|
|
ret = vert;
|
|
|
|
if (dockrect && ret != -1) {
|
|
getDockRect(ret, dockrect);
|
|
}
|
|
|
|
return ret;
|
|
}
|
|
|
|
// -----------------------------------------------------------------------
|
|
void AppBarWnd::getDockRect(int side, RECT *rect) {
|
|
LONG cxScreen, cyScreen;
|
|
RECT viewRect = {0};
|
|
Wasabi::Std::getViewport(&viewRect, hwnd, 1);
|
|
|
|
cxScreen = viewRect.right;
|
|
cyScreen = viewRect.bottom;
|
|
|
|
if (isMaximized()) {
|
|
getRestoredRect(rect);
|
|
if (renderRatioActive()) multRatio(rect);
|
|
}
|
|
else getWindowRect(rect);
|
|
|
|
Layout *l = (Layout *)getInterface(layoutGuid);
|
|
if (l) {
|
|
RECT adj;
|
|
l->getSnapAdjust(&adj);
|
|
if (renderRatioActive()) {
|
|
multRatio((int *)&adj.left, (int *)&adj.top);
|
|
multRatio((int *)&adj.right, (int *)&adj.bottom);
|
|
}
|
|
int h = rect->bottom - rect->top;
|
|
int w = rect->right - rect->left;
|
|
h -= adj.top + adj.bottom;
|
|
w -= adj.left + adj.right;
|
|
rect->left += adj.left;
|
|
rect->top += adj.top;
|
|
rect->bottom = rect->top + h;
|
|
rect->right = rect->left + w;
|
|
}
|
|
|
|
switch (side) {
|
|
case APPBAR_TOP:
|
|
case APPBAR_LEFT:
|
|
OffsetRect(rect, -rect->left, -rect->top);
|
|
break;
|
|
case APPBAR_BOTTOM:
|
|
case APPBAR_RIGHT:
|
|
OffsetRect(rect, cxScreen-rect->right, cyScreen-rect->bottom);
|
|
break;
|
|
}
|
|
|
|
switch (side) {
|
|
case APPBAR_TOP:
|
|
case APPBAR_BOTTOM:
|
|
rect->left = viewRect.left;
|
|
rect->right = cxScreen;
|
|
break;
|
|
case APPBAR_LEFT:
|
|
case APPBAR_RIGHT:
|
|
rect->top = viewRect.top;
|
|
rect->bottom = cyScreen;
|
|
break;
|
|
}
|
|
|
|
OSWINDOWHANDLE cur = getCurAutoHide(side);
|
|
int safeah = appbar_isSideAutoHideSafe(side);
|
|
|
|
if (!safeah || !(appbar_wantAutoHide() && (!cur || cur == getOsWindowHandle()))) {
|
|
straightenRect(side, rect);
|
|
}
|
|
}
|
|
|
|
// -----------------------------------------------------------------------
|
|
void AppBarWnd::updateDocking() {
|
|
if (!isVisible()) {
|
|
m_suspended = 1;
|
|
return;
|
|
}
|
|
updateSide();
|
|
appbar_updateAutoHide();
|
|
appbar_updateAlwaysOnTop();
|
|
updateTimers();
|
|
}
|
|
|
|
// -----------------------------------------------------------------------
|
|
void AppBarWnd::updateTimers() {
|
|
if (m_cur_autohide) {
|
|
if (m_cur_hiding) {
|
|
resetAutoHideTimer();
|
|
setAutoUnHideTimer();
|
|
}
|
|
else {
|
|
resetAutoUnHideTimer();
|
|
setAutoHideTimer();
|
|
}
|
|
}
|
|
}
|
|
|
|
// -----------------------------------------------------------------------
|
|
int AppBarWnd::appbar_updateAlwaysOnTop() {
|
|
if (m_side == APPBAR_NOTDOCKED) return 0;
|
|
SetWindowPos(getOsWindowHandle(), appbar_wantAlwaysOnTop() ? HWND_TOPMOST : HWND_NOTOPMOST, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE | SWP_NOACTIVATE);
|
|
return 1;
|
|
}
|
|
|
|
// -----------------------------------------------------------------------
|
|
int AppBarWnd::appbar_updateAutoHide() {
|
|
int autohide = appbar_wantAutoHide();
|
|
if (m_cur_autohide == autohide) return 0;
|
|
|
|
if (autohide && !appbar_isSideAutoHideSafe(m_cur_side)) autohide = 0;
|
|
|
|
if (m_cur_autohide == autohide) return 0;
|
|
|
|
if (autohide) {
|
|
// cur_autohide is off, turn it on
|
|
m_cur_hiding = 0;
|
|
setAutoHideTimer();
|
|
}
|
|
else {
|
|
// cur_autohide is on, turn it off
|
|
if (m_cur_hiding) resetAutoUnHideTimer();
|
|
else resetAutoHideTimer();
|
|
}
|
|
|
|
m_cur_autohide = autohide;
|
|
dock(m_cur_side);
|
|
|
|
return 1;
|
|
}
|
|
|
|
// -----------------------------------------------------------------------
|
|
void AppBarWnd::onAfterReinit() {
|
|
APPBARWND_PARENT::onAfterReinit();
|
|
m_autohide_timer_set = 0;
|
|
m_autounhide_timer_set = 0;
|
|
updateTimers();
|
|
}
|
|
|
|
// -----------------------------------------------------------------------
|
|
void AppBarWnd::setAutoHideTimer(){
|
|
if (!m_autohide_timer_set) {
|
|
SetTimer(getOsWindowHandle(), IDT_AUTOHIDE, cfg_uioptions_appbarshidetime, NULL);
|
|
m_autohide_timer_set = 1;
|
|
}
|
|
}
|
|
|
|
// -----------------------------------------------------------------------
|
|
void AppBarWnd::setAutoUnHideTimer(){
|
|
if (!m_autounhide_timer_set) {
|
|
SetTimer(getOsWindowHandle(), IDT_AUTOUNHIDE, cfg_uioptions_appbarsshowtime, NULL);
|
|
m_autounhide_timer_set = 1;
|
|
}
|
|
}
|
|
|
|
// -----------------------------------------------------------------------
|
|
void AppBarWnd::resetAutoHideTimer(){
|
|
if (m_autohide_timer_set) {
|
|
KillTimer(getOsWindowHandle(), IDT_AUTOHIDE);
|
|
m_autohide_timer_set = 0;
|
|
}
|
|
}
|
|
|
|
// -----------------------------------------------------------------------
|
|
void AppBarWnd::resetAutoUnHideTimer() {
|
|
if (m_autounhide_timer_set) {
|
|
KillTimer(getOsWindowHandle(), IDT_AUTOUNHIDE);
|
|
m_autounhide_timer_set = 0;
|
|
}
|
|
}
|
|
|
|
// -----------------------------------------------------------------------
|
|
void AppBarWnd::updateSide() {
|
|
if (m_cur_side == m_side) return;
|
|
if (m_side != m_cur_side && m_cur_side != APPBAR_NOTDOCKED && m_side != APPBAR_NOTDOCKED && m_cur_autohide) {
|
|
resetAutoHideSide(m_cur_side);
|
|
}
|
|
if (m_side == APPBAR_NOTDOCKED) unDock();
|
|
else dock(m_side);
|
|
}
|
|
|
|
// -----------------------------------------------------------------------
|
|
void AppBarWnd::resetAutoHideSide(int side) {
|
|
HWND cur = getCurAutoHide(side);
|
|
if (cur == getOsWindowHandle()) {
|
|
APPBARDATA abd;
|
|
abd.cbSize = sizeof(APPBARDATA);
|
|
abd.hWnd = cur;
|
|
abd.uEdge = side;
|
|
abd.lParam = FALSE;
|
|
SHAppBarMessage(ABM_SETAUTOHIDEBAR, &abd);
|
|
}
|
|
}
|
|
|
|
// -----------------------------------------------------------------------
|
|
void AppBarWnd::setAutoHideSide(int side) {
|
|
APPBARDATA abd;
|
|
abd.cbSize = sizeof(APPBARDATA);
|
|
abd.hWnd = getOsWindowHandle();
|
|
abd.uEdge = side;
|
|
abd.lParam = TRUE;
|
|
SHAppBarMessage(ABM_SETAUTOHIDEBAR, &abd);
|
|
}
|
|
|
|
// -----------------------------------------------------------------------
|
|
void AppBarWnd::dock(int side) {
|
|
unOwn();
|
|
|
|
if (!registerWinAppBar()) {
|
|
reOwn();
|
|
m_side = APPBAR_NOTDOCKED;
|
|
m_cur_side = APPBAR_NOTDOCKED;
|
|
m_cur_autohide = 0;
|
|
}
|
|
|
|
maximize(0);
|
|
|
|
RECT rect;
|
|
getDockRect(side, &rect);
|
|
|
|
{
|
|
RECT adj = rect;
|
|
if (ABS(getRenderRatio() - 1.0) > 0.01f) {
|
|
int _w = adj.right-adj.left;
|
|
int _h = adj.bottom-adj.top;
|
|
double rr = getRenderRatio();
|
|
_w = (int)((double)(_w) / rr + 0.5);
|
|
_h = (int)((double)(_h) / rr + 0.5);
|
|
adj.right = adj.left + _w;
|
|
adj.bottom = adj.top + _h;
|
|
}
|
|
snapAdjust(&adj, 1);
|
|
resizeToRect(&adj);
|
|
}
|
|
|
|
if (!appbar_wantAutoHide() || !appbar_isSideAutoHideSafe(side)) {
|
|
notifyWinAppBarPosition(side, rect);
|
|
}
|
|
else {
|
|
getEdge(side, &rect);
|
|
notifyWinAppBarPosition(side, rect);
|
|
setAutoHideSide(side);
|
|
m_cur_hiding = 0;
|
|
}
|
|
|
|
if (!m_suspended) appbar_onDock(side);
|
|
|
|
#ifdef WASABI_APPBAR_ONDOCKCHANGED
|
|
WASABI_APPBAR_ONDOCKCHANGED(this)
|
|
#endif
|
|
}
|
|
|
|
// -----------------------------------------------------------------------
|
|
void AppBarWnd::unDock() {
|
|
if (m_cur_side != APPBAR_NOTDOCKED) {
|
|
|
|
resetAutoHideSide(m_cur_side);
|
|
unregisterWinAppBar();
|
|
|
|
if (!m_destroying) {
|
|
reOwn();
|
|
if (!m_norestore) restore();
|
|
#ifdef WASABI_APPBAR_ONDOCKCHANGED
|
|
WASABI_APPBAR_ONDOCKCHANGED(this)
|
|
#endif
|
|
}
|
|
|
|
m_cur_side = APPBAR_NOTDOCKED;
|
|
|
|
if (!m_suspended) appbar_onUnDock();
|
|
}
|
|
}
|
|
|
|
// -----------------------------------------------------------------------
|
|
void AppBarWnd::notifyWinAppBarPosition(int side, RECT rect) {
|
|
APPBARDATA abd;
|
|
|
|
abd.cbSize = sizeof(APPBARDATA);
|
|
abd.hWnd = getOsWindowHandle();
|
|
abd.rc = rect;
|
|
abd.uEdge = side;
|
|
|
|
SHAppBarMessage(ABM_SETPOS, &abd);
|
|
m_cur_side = side;
|
|
}
|
|
|
|
// -----------------------------------------------------------------------
|
|
int AppBarWnd::appbar_isHiding() {
|
|
return m_cur_hiding;
|
|
}
|
|
|
|
// -----------------------------------------------------------------------
|
|
int AppBarWnd::appbar_isAutoHiding() {
|
|
return m_cur_autohide;
|
|
}
|
|
|
|
// -----------------------------------------------------------------------
|
|
void AppBarWnd::appbar_posChanged() {
|
|
if (m_side == APPBAR_NOTDOCKED) return;
|
|
RECT wr;
|
|
getWindowRect(&wr);
|
|
int w = wr.right-wr.left;
|
|
int h = wr.bottom-wr.top;
|
|
|
|
if (m_cur_autohide && m_cur_side != APPBAR_NOTDOCKED && !appbar_isSideAutoHideSafe(m_cur_side))
|
|
m_cur_autohide = 0;
|
|
|
|
RECT rc;
|
|
getDockRect(m_cur_side, &rc);
|
|
|
|
if (!m_cur_autohide) {
|
|
{
|
|
RECT adj = rc;
|
|
if (ABS(getRenderRatio() - 1.0) > 0.01f) {
|
|
int _w = adj.right-adj.left;
|
|
int _h = adj.bottom-adj.top;
|
|
double rr = getRenderRatio();
|
|
_w = (int)((double)(_w) / rr + 0.5);
|
|
_h = (int)((double)(_h) / rr + 0.5);
|
|
adj.right = adj.left + _w;
|
|
adj.bottom = adj.top + _h;
|
|
}
|
|
snapAdjust(&adj, 1);
|
|
resizeToRect(&adj);
|
|
}
|
|
notifyWinAppBarPosition(m_cur_side, rc);
|
|
}
|
|
else {
|
|
int aaw = appbar_getAutoHideWidthHeight();
|
|
RECT er;
|
|
getEdge(m_cur_side, &er);
|
|
notifyWinAppBarPosition(m_cur_side, er);
|
|
RECT adj = {0,0,0,0};
|
|
Layout *l = (Layout *)getInterface(layoutGuid);
|
|
if (l) l->getSnapAdjust(&adj);
|
|
if (renderRatioActive()) multRatio(&adj);
|
|
if (m_cur_hiding) {
|
|
switch (m_cur_side) {
|
|
case APPBAR_TOP:
|
|
rc.bottom = er.top + aaw + adj.bottom;
|
|
rc.top = rc.bottom - h;
|
|
break;
|
|
case APPBAR_BOTTOM:
|
|
rc.top = er.bottom - aaw - adj.top;
|
|
rc.bottom = rc.top + h;
|
|
break;
|
|
case APPBAR_LEFT:
|
|
rc.right = er.left + aaw + adj.right;
|
|
rc.left = rc.right - w;
|
|
break;
|
|
case APPBAR_RIGHT:
|
|
rc.left = er.right - aaw - adj.left;
|
|
rc.right = rc.left + w;
|
|
break;
|
|
}
|
|
}
|
|
if (ABS(getRenderRatio() - 1.0) > 0.01f) {
|
|
int _w = rc.right-rc.left;
|
|
int _h = rc.bottom-rc.top;
|
|
double rr = getRenderRatio();
|
|
_w = (int)((double)(_w) / rr + 0.5);
|
|
_h = (int)((double)(_h) / rr + 0.5);
|
|
rc.right = rc.left + _w;
|
|
rc.bottom = rc.top + _h;
|
|
}
|
|
resizeToRect(&rc);
|
|
}
|
|
}
|
|
|
|
// -----------------------------------------------------------------------
|
|
void AppBarWnd::getEdge(int side, RECT *rc) {
|
|
ASSERT(rc != NULL);
|
|
Wasabi::Std::getViewport(rc, hwnd, 1);
|
|
switch (side) {
|
|
case APPBAR_TOP:
|
|
rc->bottom = rc->top; break;
|
|
case APPBAR_BOTTOM:
|
|
rc->top = rc->bottom; break;
|
|
case APPBAR_LEFT:
|
|
rc->right = rc->left; break;
|
|
case APPBAR_RIGHT:
|
|
rc->left = rc->right; break;
|
|
}
|
|
}
|
|
|
|
// -----------------------------------------------------------------------
|
|
void AppBarWnd::appBarCallback(UINT uMsg, WPARAM wParam, LPARAM lParam) {
|
|
APPBARDATA abd = {0};
|
|
|
|
if (m_registered) {
|
|
abd.cbSize = sizeof(abd);
|
|
abd.hWnd = getOsWindowHandle();
|
|
|
|
switch (wParam)
|
|
{
|
|
// the taskbar's autohide or always-on-top state has changed.
|
|
case ABN_STATECHANGE:
|
|
DebugString("AppBarCallback: ABN_STATECHANGE\n");
|
|
break;
|
|
|
|
// a full screen application is opening or closing. we must drop
|
|
// to the bottom of the Z-Order and restore it later.
|
|
case ABN_FULLSCREENAPP:
|
|
DebugString("AppBarCallback: ABN_FULLSCREENAPP\n");
|
|
if (lParam && !m_fs) {
|
|
m_fs=1;
|
|
m_oldZOrder = GetWindow(getOsWindowHandle(), GW_HWNDPREV);
|
|
SetWindowPos(getOsWindowHandle(), HWND_BOTTOM, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE | SWP_NOACTIVATE);
|
|
}
|
|
else if (!lParam && m_fs) {
|
|
m_fs = 0;
|
|
SetWindowPos(getOsWindowHandle(), appbar_wantAlwaysOnTop() ? HWND_TOPMOST : m_oldZOrder, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE | SWP_NOACTIVATE);
|
|
m_oldZOrder = NULL;
|
|
}
|
|
break;
|
|
|
|
// something changed that may have modified the possible appbar's positions
|
|
case ABN_POSCHANGED:
|
|
DebugString("AppBarCallback: ABN_POSCHANGED\n");
|
|
appbar_posChanged();
|
|
break;
|
|
|
|
case ABN_WINDOWARRANGE:
|
|
if (lParam && !m_wahidden) {
|
|
m_wahidden = 1;
|
|
ShowWindow(getOsWindowHandle(), SW_HIDE);
|
|
}
|
|
else if (!lParam && m_wahidden) {
|
|
m_wahidden = 0;
|
|
ShowWindow(getOsWindowHandle(), SW_NORMAL);
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
// -----------------------------------------------------------------------
|
|
LRESULT AppBarWnd::wndProc( HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam )
|
|
{
|
|
if ( m_registered )
|
|
{
|
|
switch ( msg )
|
|
{
|
|
case WM_MOVE:
|
|
{
|
|
//DebugString("WM_MOVE\n");
|
|
return 0;
|
|
}
|
|
case WM_WINDOWPOSCHANGED:
|
|
{
|
|
//DebugString("WM_WINDOWPOSCHANGED\n");
|
|
//LPWINDOWPOS lpwpos = (LPWINDOWPOS)lparam;
|
|
APPBARDATA abd = { 0 };
|
|
abd.cbSize = sizeof( APPBARDATA );
|
|
abd.hWnd = getOsWindowHandle();
|
|
|
|
SHAppBarMessage( ABM_WINDOWPOSCHANGED, &abd );
|
|
}
|
|
case APPBAR_CALLBACK:
|
|
{
|
|
if ( !m_destroying ) appBarCallback( msg, wparam, lparam );
|
|
return 0;
|
|
}
|
|
case WM_DISPLAYCHANGE:
|
|
{
|
|
DebugString( "WM_DISPLAYCHANGE\n" );
|
|
appbar_posChanged();
|
|
}
|
|
case WM_TIMER:
|
|
{ // // not using multiplexed timer for independent speed
|
|
switch ( wparam )
|
|
{
|
|
case IDT_AUTOHIDE:
|
|
onAutoHideTimer();
|
|
break;
|
|
case IDT_AUTOUNHIDE:
|
|
onAutoUnHideTimer();
|
|
break;
|
|
}
|
|
}
|
|
case WM_COMMAND:
|
|
{
|
|
// forward onto the main Winamp window and let it do it
|
|
if ( HIWORD( wparam ) == THBN_CLICKED )
|
|
{
|
|
SendMessageW( plugin.hwndParent, msg, wparam, lparam );
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
return APPBARWND_PARENT::wndProc( hwnd, msg, wparam, lparam );
|
|
}
|
|
|
|
// -----------------------------------------------------------------------
|
|
void AppBarWnd::onAutoHideTimer() {
|
|
HWND me = getOsWindowHandle();
|
|
POINT pt;
|
|
RECT rc;
|
|
HWND hact;
|
|
if (m_cur_autohide) {
|
|
if (!m_cur_hiding) {
|
|
GetCursorPos(&pt);
|
|
GetWindowRect(hwnd, &rc);
|
|
snapAdjust(&rc, -1);
|
|
hact = GetForegroundWindow();
|
|
|
|
if ((!PtInRect(&rc, pt) || screenCorner(&pt)) && (hact != me) && /*(hact!= NULL) && */(GetWindowOwner(hact) != me)) {
|
|
resetAutoHideTimer();
|
|
autoHide();
|
|
setAutoUnHideTimer();
|
|
}
|
|
}
|
|
else {
|
|
resetAutoHideTimer();
|
|
setAutoUnHideTimer();
|
|
}
|
|
}
|
|
}
|
|
|
|
// -----------------------------------------------------------------------
|
|
void AppBarWnd::onAutoUnHideTimer() {
|
|
RECT rc;
|
|
POINT pt;
|
|
HWND me = getOsWindowHandle();
|
|
|
|
GetWindowRect(me, &rc);
|
|
snapAdjust(&rc, -1);
|
|
if (m_cur_autohide) {
|
|
if (m_cur_hiding) {
|
|
GetCursorPos(&pt);
|
|
if (PtInRect(&rc, pt) && !screenCorner(&pt)) {
|
|
resetAutoUnHideTimer();
|
|
autoUnHide();
|
|
setAutoHideTimer();
|
|
}
|
|
}
|
|
else {
|
|
resetAutoUnHideTimer();
|
|
setAutoHideTimer();
|
|
}
|
|
}
|
|
}
|
|
|
|
// -----------------------------------------------------------------------
|
|
void AppBarWnd::autoHide() {
|
|
if (m_cur_autohide) {
|
|
if (!m_cur_hiding) {
|
|
RECT rc;
|
|
|
|
getWindowRect(&rc);
|
|
|
|
int h = rc.bottom-rc.top;
|
|
int w = rc.right-rc.left;
|
|
|
|
int aaw = appbar_getAutoHideWidthHeight();
|
|
|
|
RECT adj={0,0,0,0};
|
|
Layout *l = static_cast<Layout*>(getInterface(layoutGuid));
|
|
l->getSnapAdjust(&adj);
|
|
if (renderRatioActive()) multRatio(&adj);
|
|
|
|
RECT viewRect = {0};
|
|
Wasabi::Std::getViewport(&viewRect, hwnd, 1);
|
|
|
|
switch (m_side) {
|
|
case APPBAR_TOP:
|
|
rc.top = -(h - aaw + adj.top - adj.bottom);
|
|
break;
|
|
case APPBAR_BOTTOM:
|
|
rc.top = (viewRect.bottom - viewRect.top) - aaw - adj.top;
|
|
break;
|
|
case APPBAR_LEFT:
|
|
rc.left = -(w - aaw + adj.left - adj.right);
|
|
break;
|
|
case APPBAR_RIGHT:
|
|
rc.left = viewRect.right - aaw - adj.left;
|
|
break;
|
|
}
|
|
|
|
switch (m_side) {
|
|
case APPBAR_TOP:
|
|
case APPBAR_BOTTOM:
|
|
rc.bottom = rc.top + h;
|
|
break;
|
|
case APPBAR_LEFT:
|
|
case APPBAR_RIGHT:
|
|
rc.right = rc.left + w;
|
|
break;
|
|
}
|
|
|
|
slideWindow(&rc);
|
|
m_cur_hiding = 1;
|
|
}
|
|
}
|
|
}
|
|
|
|
// -----------------------------------------------------------------------
|
|
void AppBarWnd::autoUnHide() {
|
|
if (m_cur_autohide) {
|
|
if (m_cur_hiding) {
|
|
m_cur_hiding = 0;
|
|
|
|
RECT rc;
|
|
getWindowRect(&rc);
|
|
|
|
int h = rc.bottom-rc.top;
|
|
int w = rc.right-rc.left;
|
|
|
|
int aaw = appbar_getAutoHideWidthHeight();
|
|
|
|
RECT adj={0,0,0,0};
|
|
Layout *l = static_cast<Layout*>(getInterface(layoutGuid));
|
|
l->getSnapAdjust(&adj);
|
|
if (renderRatioActive()) multRatio(&adj);
|
|
|
|
switch (m_side) {
|
|
case APPBAR_TOP:
|
|
rc.top += (h - aaw) - (adj.top + adj.bottom);
|
|
rc.bottom += (h - aaw) - (adj.top + adj.bottom);
|
|
break;
|
|
case APPBAR_BOTTOM:
|
|
rc.top -= (h - aaw) - (adj.top + adj.bottom);
|
|
rc.bottom -= (h - aaw) - (adj.top + adj.bottom);
|
|
break;
|
|
case APPBAR_LEFT:
|
|
rc.right += (w - aaw) - (adj.left + adj.right);
|
|
rc.left += (w - aaw) - (adj.left + adj.right);
|
|
break;
|
|
case APPBAR_RIGHT:
|
|
rc.left -= (w - aaw) - (adj.left + adj.right);
|
|
rc.right -= (w - aaw) - (adj.left + adj.right);
|
|
break;
|
|
}
|
|
|
|
slideWindow(&rc);
|
|
}
|
|
}
|
|
}
|
|
|
|
// -----------------------------------------------------------------------
|
|
|
|
const int g_dtSlideHide = 400;
|
|
const int g_dtSlideShow = 200;
|
|
|
|
// -----------------------------------------------------------------------
|
|
void AppBarWnd::slideWindow(RECT *prc) {
|
|
if (m_cur_autohide) {
|
|
m_sliding = 1;
|
|
RECT rcOld;
|
|
RECT rcNew;
|
|
int x, y, dx, dy, dt, t, t0;
|
|
BOOL fShow;
|
|
HANDLE hThreadMe;
|
|
int priority;
|
|
|
|
HWND hwnd = getOsWindowHandle();
|
|
|
|
rcNew = *prc;
|
|
|
|
/*DebugString("rcNew : left=%d, top=%d, "
|
|
"right=%d, bottom=%d\n", rcNew.left,
|
|
rcNew.top, rcNew.right, rcNew.bottom);*/
|
|
|
|
if ((g_dtSlideShow > 0) && (g_dtSlideHide > 0)) {
|
|
GetWindowRect(hwnd, &rcOld);
|
|
|
|
fShow = TRUE;/*(rcNew.bottom - rcNew.top) > (rcOld.bottom - rcOld.top) ||
|
|
(rcNew.right - rcNew.left) > (rcOld.right - rcOld.left);*/
|
|
|
|
dx = (rcNew.left - rcOld.left);
|
|
dy = (rcNew.top - rcOld.top);
|
|
|
|
if (fShow) {
|
|
rcOld = rcNew;
|
|
OffsetRect(&rcOld, -dx, -dy);
|
|
//DebugString("appbar_slideWindow %d %d\n", rcOld.left, rcOld.top);
|
|
move(rcOld.left, rcOld.top);
|
|
dt = g_dtSlideShow;
|
|
}
|
|
else {
|
|
dt = g_dtSlideHide;
|
|
}
|
|
|
|
hThreadMe = GetCurrentThread();
|
|
priority = GetThreadPriority(hThreadMe);
|
|
SetThreadPriority(hThreadMe, THREAD_PRIORITY_HIGHEST);
|
|
|
|
t0 = GetTickCount();
|
|
while ((t = GetTickCount()) < t0 + dt) {
|
|
x = rcOld.left + dx * (t - t0) / dt;
|
|
y = rcOld.top + dy * (t - t0) / dt;
|
|
|
|
//DebugString("appbar_slideWindow(2) %d %d\n", x, y);
|
|
move(x, y);
|
|
//SetWindowPos(hwnd, NULL, x, y, 0, 0, SWP_NOSIZE | SWP_NOZORDER | SWP_NOACTIVATE);
|
|
if (fShow) {
|
|
UpdateWindow(hwnd);
|
|
//invalidateWindowRegion();
|
|
//updateWindowRegion();
|
|
}
|
|
else UpdateWindow(GetDesktopWindow());
|
|
}
|
|
|
|
SetThreadPriority(hThreadMe, priority);
|
|
}
|
|
|
|
//DebugString("appbar_slideWindow(3) %d %d\n", rcNew.left, rcNew.top);
|
|
move(rcNew.left, rcNew.top);
|
|
appbar_onSlide();
|
|
}
|
|
WASABI_API_MAKI->vcpu_setComplete();
|
|
m_sliding = 0;
|
|
}
|
|
|
|
// -----------------------------------------------------------------------
|
|
void AppBarWnd::unOwn()
|
|
{
|
|
// registration was successful, we should reparent the window to NULL so that minimizing the app or changing the main AOT flag does
|
|
// nothing to this window
|
|
Layout *l = static_cast<Layout*>(getInterface(layoutGuid));
|
|
if (l) {
|
|
if (!l->getNoParent()) {
|
|
l->setNoParent(2);
|
|
// whoaaah!
|
|
reinit();
|
|
}
|
|
}
|
|
}
|
|
|
|
// -----------------------------------------------------------------------
|
|
void AppBarWnd::reOwn() {
|
|
OSWINDOWHANDLE mw = WASABI_API_WND->main_getRootWnd()->getOsWindowHandle();
|
|
if (IsIconic(mw)) ShowWindow(mw, SW_RESTORE);
|
|
// undock was successful, we should re-own the window to what it was previously. if the old owner is minimized, we should restore it first
|
|
OSWINDOWHANDLE oldparent = WASABI_API_WND->main_getRootWnd()->getOsWindowHandle();
|
|
if (IsIconic(oldparent)) ShowWindow(oldparent, SW_RESTORE);
|
|
Layout *l = static_cast<Layout *>(getInterface(layoutGuid));
|
|
if (l) {
|
|
int oldnp = l->getNoParent();
|
|
const wchar_t *np = l->getGuiObject()->guiobject_getXmlParam(L"noparent");
|
|
int newnp = WTOI(np);
|
|
if (oldnp != newnp)
|
|
{
|
|
l->setNoParent(newnp);
|
|
// whoaaah!
|
|
reinit();
|
|
}
|
|
}
|
|
}
|
|
|
|
// -----------------------------------------------------------------------
|
|
void AppBarWnd::straightenRect(int side, RECT *r) {
|
|
int w=0, h=0;
|
|
|
|
int wasregistered = m_registered;
|
|
if (!m_registered) registerWinAppBar();
|
|
|
|
APPBARDATA abd;
|
|
abd.hWnd = hwnd;
|
|
abd.cbSize = sizeof(APPBARDATA);
|
|
abd.rc = *r;
|
|
abd.uEdge = side;
|
|
|
|
RECT viewRect = {0};
|
|
Wasabi::Std::getViewport(&viewRect, hwnd, 1);
|
|
|
|
switch (side) {
|
|
case APPBAR_LEFT:
|
|
case APPBAR_RIGHT:
|
|
w = abd.rc.right - abd.rc.left;
|
|
abd.rc.top = viewRect.top;
|
|
abd.rc.bottom = viewRect.bottom;
|
|
break;
|
|
case APPBAR_TOP:
|
|
case APPBAR_BOTTOM:
|
|
h = abd.rc.bottom - abd.rc.top;
|
|
abd.rc.left = viewRect.left;
|
|
abd.rc.right = viewRect.right;
|
|
break;
|
|
}
|
|
|
|
SHAppBarMessage(ABM_QUERYPOS, &abd);
|
|
|
|
switch (abd.uEdge) {
|
|
case APPBAR_LEFT:
|
|
abd.rc.right = abd.rc.left + w;
|
|
break;
|
|
case APPBAR_RIGHT:
|
|
abd.rc.left = abd.rc.right - w;
|
|
break;
|
|
case APPBAR_TOP:
|
|
abd.rc.bottom = abd.rc.top + h;
|
|
break;
|
|
case APPBAR_BOTTOM:
|
|
abd.rc.top = abd.rc.bottom - h;
|
|
break;
|
|
}
|
|
|
|
if (!wasregistered) unregisterWinAppBar();
|
|
|
|
*r = abd.rc;
|
|
}
|
|
|
|
// -----------------------------------------------------------------------
|
|
void AppBarWnd::appbar_setNoRestore(int no) {
|
|
m_norestore = no;
|
|
}
|
|
|
|
// -----------------------------------------------------------------------
|
|
void AppBarWnd::onSetVisible( int show )
|
|
{
|
|
if ( !show && m_side != APPBAR_NOTDOCKED && !m_suspended )
|
|
{
|
|
if ( m_cur_autohide )
|
|
{
|
|
resetAutoHideSide( m_cur_side );
|
|
if ( m_cur_hiding )
|
|
resetAutoUnHideTimer();
|
|
else
|
|
resetAutoHideTimer();
|
|
}
|
|
|
|
m_suspended = 1;
|
|
unDock();
|
|
APPBARWND_PARENT::onSetVisible( show );
|
|
return;
|
|
}
|
|
else if ( show && m_suspended )
|
|
{
|
|
APPBARWND_PARENT::onSetVisible( show );
|
|
m_suspended = 0;
|
|
updateDocking();
|
|
return;
|
|
}
|
|
|
|
APPBARWND_PARENT::onSetVisible( show );
|
|
}
|
|
|
|
// -----------------------------------------------------------------------
|
|
int AppBarWnd::screenCorner(POINT *pt) {
|
|
RECT primary = {0};
|
|
Wasabi::Std::getViewport(&primary, hwnd, 1);
|
|
if (pt->x > primary.right-2 && pt->x <= primary.right) {
|
|
if (pt->y > primary.bottom-2 && pt->y <= primary.bottom) {
|
|
// bottom right corner
|
|
return 1;
|
|
}
|
|
else if (pt->y < primary.top+2 && pt->y >= primary.top) {
|
|
// top right corner
|
|
return 1;
|
|
}
|
|
}
|
|
else if (pt->x < primary.left+2 && pt->x >= primary.left) {
|
|
if (pt->y > primary.bottom-2 && pt->y <= primary.bottom) {
|
|
// bottom left corner
|
|
return 1;
|
|
}
|
|
else if (pt->y < primary.top+2 && pt->y >= primary.top) {
|
|
// top left corner
|
|
return 1;
|
|
}
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
// -----------------------------------------------------------------------
|
|
void AppBarWnd::snapAdjust(RECT *r, int way)
|
|
{
|
|
RECT s;
|
|
Layout *l = static_cast<Layout*>(getInterface(layoutGuid));
|
|
if (!l) return;
|
|
l->getSnapAdjust(&s);
|
|
int h = r->bottom - r->top;
|
|
int w = r->right - r->left;
|
|
if (way == 1) {
|
|
h += s.top + s.bottom;
|
|
w += s.left + s.right;
|
|
r->left -= s.left;
|
|
r->top -= s.top;
|
|
r->bottom = r->top + h;
|
|
r->right = r->left + w;
|
|
}
|
|
else if (way == -1) {
|
|
h -= s.top + s.bottom;
|
|
w -= s.left + s.right;
|
|
r->left += s.left;
|
|
r->top += s.top;
|
|
r->bottom = r->top + h;
|
|
r->right = r->left + w;
|
|
}
|
|
}
|
|
|
|
// -----------------------------------------------------------------------
|
|
void AppBarWnd::onRatioChanged()
|
|
{
|
|
APPBARWND_PARENT::onRatioChanged();
|
|
if (m_side != APPBAR_NOTDOCKED) appbar_posChanged();
|
|
} |