#include "BBApi.h"
#include "Workspaces.h"
#include "Settings.h"
#include "Toolbar.h"
typedef void (__stdcall *STTWTYPE)(HWND, int);
extern STTWTYPE BBSwitchToThisWindow;
extern Settings *pSettings;
extern Workspaces *pWorkspaces;
extern Toolbar *pToolbar;
extern Systembar *pSystembar;
const char szWorkspacesName[] = "Workspaces";
Workspaces::Workspaces(HINSTANCE hMainInstance)
{
WNDCLASS wc;
if (pSettings->usingWin2kXP)
{
ScreenWidth = GetSystemMetrics(SM_CXVIRTUALSCREEN);
ScreenHeight = GetSystemMetrics(SM_CYVIRTUALSCREEN);
}
else
{
ScreenWidth = GetSystemMetrics(SM_CXSCREEN);
ScreenHeight = GetSystemMetrics(SM_CYSCREEN);
}
currentScreen=0;
lastScreen = 0;
flushNames();
inst = hMainInstance;
ZeroMemory(&wc,sizeof(wc));
wc.lpfnWndProc = WndProc;
wc.hInstance = inst;
wc.lpszClassName = szWorkspacesName;
if (!RegisterClass(&wc))
{
MessageBox(0,"Error registering window class.",szWorkspacesName,MB_OK);
Log("Could not register Workspaces Class", NULL);
}
hWorkWnd = CreateWindowEx(
WS_EX_TOOLWINDOW,
szWorkspacesName,
NULL,
0,
0, 0,
0, 0,
NULL,
NULL,
inst,
0);
if (!hWorkWnd)
{
UnregisterClass(szWorkspacesName,inst);
MessageBox(0,"Error creating window",szWorkspacesName,MB_OK);
Log("Could not create the BBWorkspace Window", NULL);
return;
}
int msgs[] = { BB_WORKSPACE, BB_RECONFIGURE, BB_SWITCHTON, BB_ACTIVETASK, BB_LISTDESKTOPS, BB_BRINGTOFRONT, 0 };
SendMessage(GetBBWnd(), BB_REGISTERMESSAGE, (WPARAM)hWorkWnd, (LPARAM)msgs);
MakeSticky(hWorkWnd);
}
Workspaces::~Workspaces()
{
GatherWindows();
int msgs[] = { BB_WORKSPACE, BB_RECONFIGURE, BB_SWITCHTON, BB_ACTIVETASK, BB_LISTDESKTOPS, BB_BRINGTOFRONT, 0 };
SendMessage(GetBBWnd(), BB_UNREGISTERMESSAGE, (WPARAM)hWorkWnd, (LPARAM)msgs);
DestroyWindow(hWorkWnd);
UnregisterClass(szWorkspacesName,inst);
deskNames.clear();
}
LRESULT CALLBACK WndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
{
switch (message)
{
case BB_RECONFIGURE:
pWorkspaces->flushNames();
break;
case BB_SWITCHTON:
{
int i = (int)wParam;
if ((pWorkspaces->currentScreen != i))
pWorkspaces->switchToDesktop(i);
break;
}
case BB_ACTIVETASK:
{
if (pSettings->followActive) pWorkspaces->switchToDesktop(pWorkspaces->getDesktop((HWND)wParam));
}
case BB_LISTDESKTOPS:
{
DesktopInfo deskInfo;
for(int i = 0; i < pSettings->workspaces; i++)
{
deskInfo.isCurrent = (pWorkspaces->currentScreen == i);
deskInfo.number = i;
if(pWorkspaces->deskNames[i]=="null")
sprintf(deskInfo.name, "Workspace %d", i + 1);
else
strcpy(deskInfo.name, pWorkspaces->deskNames[i].c_str());
SendMessage((HWND)wParam, BB_DESKTOPINFO, 0, (LPARAM) &deskInfo);
}
break;
}
case BB_BRINGTOFRONT:
{
int n = pWorkspaces->getDesktop((HWND)lParam);
if (n != pWorkspaces->currentScreen)
pWorkspaces->switchToDesktop(n);
BBSwitchToThisWindow((HWND)lParam, 1);
break;
}
case BB_WORKSPACE:
{
switch (wParam)
{
case 0:
pWorkspaces->DeskLeft();
break;
case 1:
pWorkspaces->DeskRight();
break;
case 2:
pWorkspaces->AddDesktop();
break;
case 3:
pWorkspaces->DelDesktop();
break;
case 4:
pWorkspaces->DeskSwitch((int)lParam);
break;
case 5:
pWorkspaces->GatherWindows();
break;
case 6:
pWorkspaces->MoveWindowToPrev((HWND)lParam);
break;
case 7:
pWorkspaces->MoveWindowToNext((HWND)lParam);
break;
case 8:
pWorkspaces->PrevWindow((int)lParam);
break;
case 9:
pWorkspaces->NextWindow((int)lParam);
break;
case 10:
pWorkspaces->LastDesk();
break;
default:
pWorkspaces->DeskLeft();
}
}
break;
case WM_DISPLAYCHANGE:
{
if (pSettings->usingWin2kXP)
{
pWorkspaces->ScreenWidth = GetSystemMetrics(SM_CXVIRTUALSCREEN);
pWorkspaces->ScreenHeight = GetSystemMetrics(SM_CYVIRTUALSCREEN);
}
else
{
pWorkspaces->ScreenWidth = GetSystemMetrics(SM_CXSCREEN);
pWorkspaces->ScreenHeight = GetSystemMetrics(SM_CYSCREEN);
}
}
default:
return DefWindowProc(hwnd,message,wParam,lParam);
}
return 0;
}
const long magicDWord = 0x49474541;
BOOL CALLBACK EnumWindowsProc( HWND hwnd, LPARAM lParam )
{
int width;
int addH = (INT)lParam;
int ScreenWidth = pWorkspaces->ScreenWidth;
RECT r;
if (!(GetWindowLong(hwnd, GWL_STYLE) & WS_VISIBLE))
return true;
if (pWorkspaces->CheckWindow(hwnd))
return true;
if (CheckSticky(hwnd))
return true;
if (GetWindowLong(hwnd, GWLP_USERDATA) == magicDWord)
return true;
GetWindowRect(hwnd, &r);
if (addH == -1)
{
width = abs(r.right - r.left);
if (r.left > ScreenWidth)
{
r.left %= (ScreenWidth + 10);
if (r.left > ScreenWidth)
r.left -= (ScreenWidth + 10);
r.right = r.left + width;
}
else if (r.left < -10)
{
r.left %= (ScreenWidth + 10);
while (r.left < -10)
r.left += (ScreenWidth + 10);;
r.right = r.left + width;
}
}
else
{
r.left-=addH;
r.right-=addH;
}
pWorkspaces->dwp = DeferWindowPos(pWorkspaces->dwp, hwnd, NULL, r.left, r.top, r.right-r.left, r.bottom-r.top, SWP_NOZORDER|SWP_NOACTIVATE);
return true;
}
bool Workspaces::CheckWindow(HWND window)
{
char appName[MAX_PATH], entryName[MAX_PATH];
GetWindowText(window, appName, MAX_PATH);
strlwr(appName);
for (int i = 0; i < (int)stickyList.size(); i++)
{
strcpy(entryName, stickyList[i].c_str());
strlwr(entryName);
if (!strcmp(appName, entryName))
return true;
}
return CheckSticky(window);
}
void Workspaces::switchToDesktop(int vw)
{
if (vw != currentScreen && vw >= 0 && vw < pSettings->workspaces)
{
INT addH = ((vw % pSettings->workspaces) - (currentScreen % pSettings->workspaces)) * (ScreenWidth + 10);
dwp = BeginDeferWindowPos(1);
EnumWindows(EnumWindowsProc, (LPARAM)addH);
EndDeferWindowPos(dwp);
lastScreen = currentScreen;
currentScreen = vw;
}
if (!pSettings->accessLock)
{
if (pToolbar) InvalidateRect(pToolbar->hToolbarWnd, NULL, false);
if (pSystembar && pSettings->taskbarCurrentOnly) InvalidateRect(pSystembar->hSystembarWnd, NULL, false);
}
}
void Workspaces::GatherWindows()
{
dwp = BeginDeferWindowPos(1);
EnumWindows(EnumWindowsProc, (LPARAM)-1);
EndDeferWindowPos(dwp);
if (!pSettings->accessLock)
{
if (pSystembar && pSettings->taskbarCurrentOnly) InvalidateRect(pSystembar->hSystembarWnd, NULL, false);
}
}
int Workspaces::getDesktop(HWND h)
{
if (!h || IsIconic(h)) return 255;
RECT r;
GetWindowRect(h, &r);
return (getDesktopByRect(r));
}
int Workspaces::getDesktopByRect(RECT r)
{
int offsetx = currentScreen % pSettings->workspaces;
int offsety = currentScreen / pSettings->workspaces;
int desk;
RECT tmpRect, desktopRect;
desktopRect.left = desktopRect.top = 0;
desktopRect.right = ScreenWidth;
desktopRect.bottom = ScreenHeight;
if (IntersectRect(&tmpRect, &r, &desktopRect))
return currentScreen;
r.left += offsetx * (ScreenWidth + 10);
r.top += offsety * (ScreenHeight + 10);
offsetx = ((r.left + 10) / (ScreenWidth + 10));
offsety = ((r.top + 10) / (ScreenHeight + 10));
desk = (offsety * pSettings->workspaces) + offsetx;
if (desk < 0 || desk > pSettings->workspaces)
desk = currentScreen;
return desk;
}
void Workspaces::AddDesktop()
{
if (pSettings->workspaces == 253) return;
pSettings->workspaces++;
flushNames();
WriteInt(bbrcPath(), "session.screen0.workspaces:", pSettings->workspaces);
}
void Workspaces::DelDesktop()
{
if (pSettings->workspaces != 1)
{
if (currentScreen == pSettings->workspaces - 1)
switchToDesktop(currentScreen-1);
pSettings->workspaces--;
flushNames();
}
WriteInt(bbrcPath(), "session.screen0.workspaces:", pSettings->workspaces);
}
void Workspaces::DeskLeft()
{
int vwm = (currentScreen > 0) ? (currentScreen - 1) : (pSettings->workspaces - 1);
switchToDesktop(vwm);
}
void Workspaces::DeskRight()
{
int vwm = (currentScreen < pSettings->workspaces - 1) ? (currentScreen + 1) : 0;
switchToDesktop(vwm);
}
void Workspaces::LastDesk()
{
switchToDesktop(lastScreen);
}
void Workspaces::DeskSwitch(int i)
{
switchToDesktop(i);
}
void Workspaces::MoveWindowToSpecified(HWND window, int workspace)
{
if (CheckSticky(window)) return;
switchToDesktop(getDesktop(window));
BBSwitchToThisWindow(window, true);
MakeSticky(window);
switchToDesktop(workspace);
RemoveSticky(window);
if (!pSettings->accessLock)
{
if (!pSettings->taskbarOnToolbar && pSystembar && pSettings->taskbarCurrentOnly) InvalidateRect(pSystembar->hSystembarWnd, NULL, false);
else if (pToolbar && pSettings->taskbarCurrentOnly) InvalidateRect(pToolbar->hToolbarWnd, NULL, false);
}
}
void Workspaces::MoveWindowToPrev(HWND window)
{
if (currentScreen == 0) MoveWindowToSpecified(window, pSettings->workspaces);
else MoveWindowToSpecified(window, currentScreen-1);
}
void Workspaces::MoveWindowToNext(HWND window)
{
if (currentScreen == pSettings->workspaces) MoveWindowToSpecified(window, 0);
else MoveWindowToSpecified(window, currentScreen+1);
}
void Workspaces::PrevWindow(int allDesktops)
{
HWND BBWnd = GetBBWnd();
HWND hTempWnd = GetWindow(BBWnd, GW_HWNDLAST);
HWND hTempWndLast = GetWindow(BBWnd, GW_HWNDFIRST);
HWND hProgManWnd = FindWindow("Progman", "Program Manager");
if (hTempWnd == hProgManWnd) hTempWnd = GetWindow(hTempWnd, GW_HWNDPREV);
while (!(IsWindowVisible(hTempWnd)) | IsIconic(hTempWnd) | !(GetWindowTextLength(hTempWnd)))
{
hTempWnd = GetWindow(hTempWnd, GW_HWNDPREV);
if (allDesktops == 0)
{
while (getDesktop(hTempWnd) != currentScreen)
{
hTempWnd = GetWindow(hTempWnd, GW_HWNDPREV);
if (hTempWnd == hProgManWnd) hTempWnd = GetWindow(hTempWnd, GW_HWNDPREV);
}
}
else if (hTempWnd == hProgManWnd) hTempWnd = GetWindow(hTempWnd, GW_HWNDPREV);
if (hTempWnd == hTempWndLast) break;
}
if (IsWindow(hTempWnd))
{
SetWindowPos(hTempWnd, HWND_TOP, 0, 0, 0, 0, SWP_NOSIZE | SWP_NOMOVE);
SendMessage(BBWnd, BB_BRINGTOFRONT, 0, (LPARAM)hTempWnd);
}
}
void Workspaces::NextWindow(int allDesktops)
{
HWND BBWnd = GetBBWnd();
HWND hTempWnd = GetWindow(BBWnd, GW_HWNDFIRST);
HWND hProgManWnd = FindWindow("Progman", "Program Manager");
if (hTempWnd == hProgManWnd) hTempWnd = GetWindow(hTempWnd, GW_HWNDNEXT);
while (!(IsWindowVisible(hTempWnd)) | IsIconic(hTempWnd) | !(GetWindowTextLength(hTempWnd)))
{
hTempWnd = GetWindow(hTempWnd, GW_HWNDNEXT);
if (hTempWnd == NULL) break;
if (allDesktops == 0)
{
while (getDesktop(hTempWnd) != currentScreen)
{
hTempWnd = GetWindow(hTempWnd, GW_HWNDNEXT);
if (hTempWnd == hProgManWnd) hTempWnd = GetWindow(hTempWnd, GW_HWNDNEXT);
if (hTempWnd == NULL) break;
}
}
else if (hTempWnd == hProgManWnd) hTempWnd = GetWindow(hTempWnd, GW_HWNDNEXT);
}
if (IsWindow(hTempWnd))
{
HWND hTempWndBottom = GetWindow(BBWnd, GW_HWNDLAST);
if (hTempWndBottom == hProgManWnd) hTempWndBottom = GetWindow(hTempWndBottom, GW_HWNDPREV);
while (!(IsWindowVisible(hTempWndBottom)) | IsIconic(hTempWndBottom) | !(GetWindowTextLength(hTempWndBottom)))
{
hTempWndBottom = GetWindow(hTempWndBottom, GW_HWNDPREV);
if (hTempWndBottom == NULL) break;
if (allDesktops == 0)
{
while (getDesktop(hTempWndBottom) != currentScreen)
{
hTempWndBottom = GetWindow(hTempWndBottom, GW_HWNDPREV);
if (hTempWndBottom == hProgManWnd) hTempWndBottom = GetWindow(hTempWndBottom, GW_HWNDPREV);
if (hTempWndBottom == NULL) break;
}
}
else
{
if (hTempWndBottom == hProgManWnd) hTempWndBottom = GetWindow(hTempWndBottom, GW_HWNDPREV);
}
}
HWND hTempWndNext = GetWindow(hTempWnd, GW_HWNDNEXT);
if (hTempWndNext == hProgManWnd) hTempWndNext = GetWindow(hTempWndNext, GW_HWNDNEXT);
while (!(IsWindowVisible(hTempWndNext)) | IsIconic(hTempWndNext) | !(GetWindowTextLength(hTempWndNext)))
{
hTempWndNext = GetWindow(hTempWndNext, GW_HWNDNEXT);
if (hTempWndNext == NULL) break;
if (allDesktops == 0)
{
while (getDesktop(hTempWndNext) != currentScreen)
{
hTempWndNext = GetWindow(hTempWndNext, GW_HWNDNEXT);
if (hTempWndNext == hProgManWnd) hTempWndNext = GetWindow(hTempWndNext, GW_HWNDNEXT);
if (hTempWndNext == NULL) break;
}
}
else if (hTempWndNext == hProgManWnd) hTempWndNext = GetWindow(hTempWndNext, GW_HWNDNEXT);
}
if (IsWindow(hTempWnd) && IsWindow(hTempWndBottom))
{
SetWindowPos(hTempWnd, hTempWndBottom, 0, 0, 0, 0, SWP_NOACTIVATE | SWP_NOSIZE | SWP_NOMOVE | SWP_NOSENDCHANGING);
if (IsWindow(hTempWndNext))
{
SetWindowPos(hTempWndNext, HWND_TOP, 0, 0, 0, 0, SWP_NOSIZE | SWP_NOMOVE);
SendMessage(BBWnd, BB_BRINGTOFRONT, 0, (LPARAM)hTempWndNext);
}
}
}
}
void Workspaces::flushNames()
{
deskNames.clear();
char buffer[MAX_LINE_LENGTH], szBuffer[MAX_PATH];
strcpy(buffer, pSettings->workspaceNames);
for (int i = 0; i < pSettings->workspaces; i++)
{
strcpy(buffer, Tokenize(buffer, szBuffer, ","));
if (!strcmp(szBuffer,"")) strcpy(szBuffer, "null");
deskNames.push_back(string(szBuffer));
}
}
syntax highlighting by