X-Git-Url: https://git.reactos.org/?p=reactos.git;a=blobdiff_plain;f=reactos%2Fsubsys%2Fsystem%2Fexplorer%2Fdesktop%2Fdesktop.cpp;h=21ecd83e309229f197b8c78467af2f17666f9b76;hp=b12df79c5f5b799d77a206f79402385353d6c576;hb=8441c8115e89407aeceb49bf269758d7e111a2c2;hpb=7562cce403f2ec5c1dea557b80b2f4ef92379c70 diff --git a/reactos/subsys/system/explorer/desktop/desktop.cpp b/reactos/subsys/system/explorer/desktop/desktop.cpp index b12df79c5f5..21ecd83e309 100644 --- a/reactos/subsys/system/explorer/desktop/desktop.cpp +++ b/reactos/subsys/system/explorer/desktop/desktop.cpp @@ -1,5 +1,5 @@ /* - * Copyright 2003, 2004 Martin Fuchs + * Copyright 2003, 2004, 2005 Martin Fuchs * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -18,7 +18,7 @@ // - // Explorer clone, lean version + // Explorer clone // // desktop.cpp // @@ -28,16 +28,41 @@ #include "precomp.h" +#include "../explorer_intres.h" + #include "../taskbar/desktopbar.h" #include "../taskbar/taskbar.h" // for PM_GET_LAST_ACTIVE -#include "../explorer_intres.h" - static BOOL (WINAPI*SetShellWindow)(HWND); static BOOL (WINAPI*SetShellWindowEx)(HWND, HWND); +#ifdef _USE_HDESK + +Desktop::Desktop(HDESK hdesktop/*, HWINSTA hwinsta*/) + : _hdesktop(hdesktop) +// _hwinsta(hwinsta) +{ +} + +Desktop::~Desktop() +{ + if (_hdesktop) + CloseDesktop(_hdesktop); + +// if (_hwinsta) +// CloseWindowStation(_hwinsta); + + if (_pThread.get()) { + _pThread->Stop(); + _pThread.release(); + } +} + +#endif + + Desktops::Desktops() : _current_desktop(0) { @@ -54,14 +79,84 @@ Desktops::~Desktops() void Desktops::init() { resize(DESKTOP_COUNT); + +#ifdef _USE_HDESK + DesktopPtr& desktop = (*this)[0]; + + desktop = DesktopPtr(new Desktop(OpenInputDesktop(0, FALSE, DESKTOP_SWITCHDESKTOP))); +#endif } +#ifdef _USE_HDESK + +void Desktops::SwitchToDesktop(int idx) +{ + if (_current_desktop == idx) + return; + + DesktopPtr& desktop = (*this)[idx]; + + DesktopThread* pThread = NULL; + + if (desktop.get()) { + if (desktop->_hdesktop) + if (!SwitchDesktop(desktop->_hdesktop)) + return; + } else { + FmtString desktop_name(TEXT("Desktop %d"), idx); + + SECURITY_ATTRIBUTES saAttr = {sizeof(SECURITY_ATTRIBUTES), 0, TRUE}; +/* + HWINSTA hwinsta = CreateWindowStation(TEXT("ExplorerWinStation"), 0, GENERIC_ALL, &saAttr); + + if (!SetProcessWindowStation(hwinsta)) + return; +*/ + HDESK hdesktop = CreateDesktop(desktop_name, NULL, NULL, 0, GENERIC_ALL, &saAttr); + if (!hdesktop) + return; + + desktop = DesktopPtr(new Desktop(hdesktop/*, hwinsta*/)); + + pThread = new DesktopThread(*desktop); + } + + _current_desktop = idx; + + if (pThread) { + desktop->_pThread = DesktopThreadPtr(pThread); + pThread->Start(); + } +} + +int DesktopThread::Run() +{ + if (!SetThreadDesktop(_desktop._hdesktop)) + return -1; + + HDESK hDesk_old = OpenInputDesktop(0, FALSE, DESKTOP_SWITCHDESKTOP); + + if (!SwitchDesktop(_desktop._hdesktop)) + return -1; + + if (!_desktop._hwndDesktop) + _desktop._hwndDesktop = DesktopWindow::Create(); + + int ret = Window::MessageLoop(); + + SwitchDesktop(hDesk_old); + + return ret; +} + +#else // _USE_HDESK + static BOOL CALLBACK SwitchDesktopEnumFct(HWND hwnd, LPARAM lparam) { WindowSet& windows = *(WindowSet*)lparam; - if (IsWindowVisible(hwnd)) - if (hwnd!=g_Globals._hwndDesktopBar && hwnd!=g_Globals._hwndDesktop) + if (hwnd!=g_Globals._hwndDesktopBar && hwnd!=g_Globals._hwndDesktop) + if (IsWindowVisible(hwnd)) windows.insert(hwnd); return TRUE; @@ -110,17 +205,24 @@ void Desktops::SwitchToDesktop(int idx) _current_desktop = idx; } +#endif // _USE_HDESK + static BOOL CALLBACK MinimizeDesktopEnumFct(HWND hwnd, LPARAM lparam) { list& minimized = *(list*)lparam; - if (IsWindowVisible(hwnd)) - if (hwnd!=g_Globals._hwndDesktopBar && hwnd!=g_Globals._hwndDesktop) - if (!IsIconic(hwnd)) { + if (hwnd!=g_Globals._hwndDesktopBar && hwnd!=g_Globals._hwndDesktop) + if (IsWindowVisible(hwnd) && !IsIconic(hwnd)) { + RECT rect; + + if (GetWindowRect(hwnd,&rect)) + if (rect.right>0 && rect.bottom>0 && + rect.right>rect.left && rect.bottom>rect.top) { minimized.push_back(MinimizeStruct(hwnd, GetWindowStyle(hwnd))); ShowWindowAsync(hwnd, SW_MINIMIZE); } + } return TRUE; } @@ -170,7 +272,9 @@ LRESULT BackgroundWindow::WndProc(UINT nmsg, WPARAM wparam, LPARAM lparam) return TRUE; case WM_MBUTTONDBLCLK: - explorer_show_frame(SW_SHOWNORMAL); + /* Imagelist icons are missing if MainFrame::Create() is called directly from here! + explorer_show_frame(SW_SHOWNORMAL); */ + PostMessage(g_Globals._hwndDesktop, nmsg, wparam, lparam); break; case PM_DISPLAY_VERSION: @@ -179,6 +283,8 @@ LRESULT BackgroundWindow::WndProc(UINT nmsg, WPARAM wparam, LPARAM lparam) DWORD reset_mask = LOWORD(lparam); DWORD xor_mask = HIWORD(lparam); _display_version = ((_display_version&~reset_mask) | or_mask) ^ xor_mask; + RegSetDWORDValue(HKEY_CURRENT_USER, TEXT("Control Panel\\Desktop"), TEXT("PaintDesktopVersion"), _display_version); + ///@todo Changing the PaintDesktopVersion-Flag needs a restart of the shell -> display a message box InvalidateRect(_hwnd, NULL, TRUE); } return _display_version; @@ -199,27 +305,6 @@ void BackgroundWindow::DrawDesktopBkgnd(HDC hdc) FillRect(hdc, &rect, bkgndBrush); DeleteBrush(bkgndBrush); */ - if (_display_version) { - static const String s_bkgnd_txt = ResString(IDS_EXPLORER_VERSION_STR) + TEXT("\nby Martin Fuchs"); - - FmtString txt(s_bkgnd_txt, (LPCTSTR)ResString(IDS_VERSION_STR)); - ClientRect rect(_hwnd); - - rect.left = rect.right - 280; - rect.top = rect.bottom - 80 - DESKTOPBARBAR_HEIGHT; - rect.right = rect.left + 250; - rect.bottom = rect.top + 40; - - BkMode bkMode(hdc, TRANSPARENT); - - TextColor textColor(hdc, RGB(128,128,192)); - DrawText(hdc, txt, -1, &rect, DT_RIGHT); - - SetTextColor(hdc, RGB(255,255,255)); - --rect.right; - ++rect.top; - DrawText(hdc, txt, -1, &rect, DT_RIGHT); - } } @@ -246,7 +331,7 @@ HWND DesktopWindow::Create() int height = GetSystemMetrics(SM_CYSCREEN); HWND hwndDesktop = Window::Create(WINDOW_CREATOR(DesktopWindow), - WS_EX_TOOLWINDOW, wcDesktop, TEXT("Program Manager"), WS_POPUP|WS_VISIBLE|WS_CLIPCHILDREN, + WS_EX_TOOLWINDOW, wcDesktop, TEXT("Program Manager"), WS_POPUP|WS_VISIBLE, //|WS_CLIPCHILDREN for SDI frames 0, 0, width, height, 0); // work around to display desktop bar in Wine @@ -356,7 +441,7 @@ LRESULT DesktopWindow::WndProc(UINT nmsg, WPARAM wparam, LPARAM lparam) case WM_DESTROY: ///@todo use IShellBrowser::GetViewStateStream() and _pShellView->SaveViewState() to store view state - + if (SetShellWindow) SetShellWindow(0); break; @@ -383,7 +468,7 @@ LRESULT DesktopWindow::WndProc(UINT nmsg, WPARAM wparam, LPARAM lparam) HRESULT DesktopWindow::OnDefaultCommand(LPIDA pida) { #ifndef ROSSHELL // in shell-only-mode fall through and let shell32 handle the command - if (MainFrame::OpenShellFolders(pida, 0)) + if (MainFrameBase::OpenShellFolders(pida, 0)) return S_OK; #endif @@ -407,6 +492,9 @@ DesktopShellView::DesktopShellView(HWND hwnd, IShellView* pShellView) // subclass background window new BackgroundWindow(_hwndListView); + _icon_algo = 1; // default icon arrangement + + PositionIcons(); InitDragDrop(); } @@ -445,10 +533,18 @@ LRESULT DesktopShellView::WndProc(UINT nmsg, WPARAM wparam, LPARAM lparam) { switch(nmsg) { case WM_CONTEXTMENU: - if (!DoContextMenu(GET_X_LPARAM(lparam), GET_Y_LPARAM(lparam), _cm_ifs)) + if (!DoContextMenu(GET_X_LPARAM(lparam), GET_Y_LPARAM(lparam))) DoDesktopContextMenu(GET_X_LPARAM(lparam), GET_Y_LPARAM(lparam)); break; + case PM_SET_ICON_ALGORITHM: + _icon_algo = wparam; + PositionIcons(); + break; + + case PM_GET_ICON_ALGORITHM: + return _icon_algo; + case PM_DISPLAY_VERSION: return SendMessage(_hwndListView, nmsg, wparam, lparam); @@ -469,7 +565,7 @@ int DesktopShellView::Notify(int id, NMHDR* pnmh) return super::Notify(id, pnmh); } -bool DesktopShellView::DoContextMenu(int x, int y, CtxMenuInterfaces& cm_ifs) +bool DesktopShellView::DoContextMenu(int x, int y) { IDataObject* selection; @@ -499,7 +595,7 @@ bool DesktopShellView::DoContextMenu(int x, int y, CtxMenuInterfaces& cm_ifs) for(int i=pida->cidl; i>0; --i) apidl[i-1] = (LPCITEMIDLIST) ((LPBYTE)pida+pida->aoffset[i]); - hr = ShellFolderContextMenu(ShellFolder(parent_pidl), _hwnd, pida->cidl, apidl, x, y, cm_ifs); + hr = ShellFolderContextMenu(ShellFolder(parent_pidl), _hwnd, pida->cidl, apidl, x, y, _cm_ifs); selection->Release(); @@ -555,3 +651,177 @@ HRESULT DesktopShellView::DoDesktopContextMenu(int x, int y) return hr; } + + +#define ARRANGE_BORDER_DOWN 8 +#define ARRANGE_BORDER_HV 9 +#define ARRANGE_ROUNDABOUT 10 + +static const POINTS s_align_start[] = { + {0, 0}, // left/top + {0, 0}, + {1, 0}, // right/top + {1, 0}, + {0, 1}, // left/bottom + {0, 1}, + {1, 1}, // right/bottom + {1, 1}, + + {0, 0}, // left/top + {0, 0}, + {0, 0} +}; + +static const POINTS s_align_dir1[] = { + { 0, +1}, // down + {+1, 0}, // right + {-1, 0}, // left + { 0, +1}, // down + { 0, -1}, // up + {+1, 0}, // right + {-1, 0}, // left + { 0, -1}, // up + + { 0, +1}, // down + {+1, 0}, // right + {+1, 0} // right +}; + +static const POINTS s_align_dir2[] = { + {+1, 0}, // right + { 0, +1}, // down + { 0, +1}, // down + {-1, 0}, // left + {+1, 0}, // right + { 0, -1}, // up + { 0, -1}, // up + {-1, 0}, // left + + {+1, 0}, // right + { 0, +1}, // down + { 0, +1} // down +}; + +typedef pair IconPos; +typedef map IconMap; + +void DesktopShellView::PositionIcons(int dir) +{ + DWORD spacing = ListView_GetItemSpacing(_hwndListView, FALSE); + + RECT work_area; + SystemParametersInfo(SPI_GETWORKAREA, 0, &work_area, 0); + + const POINTS& dir1 = s_align_dir1[_icon_algo]; + const POINTS& dir2 = s_align_dir2[_icon_algo]; + const POINTS& start_pos = s_align_start[_icon_algo]; + + int dir_x1 = dir1.x; + int dir_y1 = dir1.y; + int dir_x2 = dir2.x; + int dir_y2 = dir2.y; + + int cx = LOWORD(spacing); + int cy = HIWORD(spacing); + + int dx1 = dir_x1 * cx; + int dy1 = dir_y1 * cy; + int dx2 = dir_x2 * cx; + int dy2 = dir_y2 * cy; + + int start_x = (start_pos.x * work_area.right)/cx*cx + (cx-32)/2; + int start_y = (start_pos.y * work_area.bottom)/cy*cy + 4/*(cy-32)/2*/; + + if (start_x >= work_area.right) + start_x -= cx; + + if (start_y >= work_area.bottom) + start_y -= cy; + + int x = start_x; + int y = start_y; + + int all = ListView_GetItemCount(_hwndListView); + int i1, i2; + + if (dir > 0) { + i1 = 0; + i2 = all; + } else { + i1 = all-1; + i2 = -1; + } + + IconMap pos_idx; + int cnt = 0; + + for(int idx=i1; idx!=i2; idx+=dir) { + pos_idx[IconPos(y, x)] = idx; + + if (_icon_algo == ARRANGE_BORDER_DOWN) { + if (++cnt & 1) + x = work_area.right - x; + else { + y += dy1; + + if (y >= work_area.bottom) { + y = start_y; + x += dx2; + } + } + + continue; + } + else if (_icon_algo == ARRANGE_BORDER_HV) { + if (++cnt & 1) + x = work_area.right - x; + else if (cnt & 2) { + y += dy1; + + if (y >= work_area.bottom) { + y = start_y; + x += dx2; + } + } else { + x += dx1; + + if (x >= work_area.right) { + x = start_x; + y += dy2; + } + } + + continue; + } + else if (_icon_algo == ARRANGE_ROUNDABOUT) { + + ///@todo + + } + + x += dx1; + y += dy1; + + if (x<0 || x>=work_area.right) { + x = start_x; + y += dy2; + } else if (y<0 || y>=work_area.bottom) { + y = start_y; + x += dx2; + } + } + + // use a little trick to get the icons where we want them to be... + + for(IconMap::const_iterator it=pos_idx.end(); --it!=pos_idx.begin(); ) { + const IconPos& pos = it->first; + + ListView_SetItemPosition32(_hwndListView, it->second, pos.second, pos.first); + } + + for(IconMap::const_iterator it=pos_idx.begin(); it!=pos_idx.end(); ++it) { + const IconPos& pos = it->first; + + ListView_SetItemPosition32(_hwndListView, it->second, pos.second, pos.first); + } +}