////////////////////////////////////////////////////////////////////////// //// Win32 Event Listeners ////////////////////////////////////////////////////////////////////////// LRESULT ViWmManager::HandleShellHook( HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam ) { if (msg != shellhookid) return DefWindowProc(hwnd, msg, wParam, lParam); TilledWindow *found; switch (wParam) { case HSHELL_WINDOWCREATED: if (TilledWindow::IsHandleTileable((HWND)lParam)) { AddNode((HWND)lParam); ArrangeWindows(); FocusCurrent(); selectWindow( (HWND)lParam ); _ASSERTE( _CrtCheckMemory() == TRUE ); } break; case HSHELL_WINDOWDESTROYED: found = currentState.FindNode((HWND)lParam); if ( found ) { for (size_t i = 0; i < currentLayout.size(); ++i) LayoutTree::removeClean( currentLayout[i].layoutRoot, (HWND) lParam ); currentState.RemoveNode((HWND)lParam, false); ArrangeWindows(); FocusCurrent(); _ASSERTE( _CrtCheckMemory() == TRUE ); } break; case HSHELL_RUDEAPPACTIVATED: case HSHELL_WINDOWACTIVATED: if (globalManager->inDrag()) break; found = currentState.FindNode((HWND)lParam); if (found) { if (currentState.current) { currentState.current->SetTransparency( globalManager->conf.idleTransparency() ); } currentState.current = found; found->SetTransparency( 255 ); selectWindow( (HWND)lParam ); FocusCurrent(); } _ASSERTE( _CrtCheckMemory() == TRUE ); break; } return 0; }
LRESULT CALLBACK WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) { node *current = NULL; node *nodes; unsigned short tag; switch (msg) { case WM_CREATE: if (experimental_mouse) { SetTimer(hwnd, TIMER_UPDATE_MOUSE, 500, NULL); // Poll for mouse position } break; case WM_CLOSE: { ClipCursor(0); // Release Cursor Lock DeregisterShellHookWindow(hwnd); UnregisterHotkeys(hwnd); if (experimental_mouse) { KillTimer(hwnd, TIMER_UPDATE_MOUSE); // Mouse Poll Timer } for (tag=0; tag<TAGS; tag++) { nodes = tags[tag].nodes; for (current = nodes; current;) { node *next = current->next; RestoreWindow(current->hwnd); RemoveNode(current->hwnd, tag); current = next; } DestroyWindow(hwnd); } } break; case WM_DESTROY: PostQuitMessage(WM_QUIT); break; case WM_HOTKEY: if (wParam >= KEY_TOGGLE_T1 && wParam < (KEY_TOGGLE_T1 + TAGS)) { ToggleTag(wParam - KEY_TOGGLE_T1); break; } else if (wParam >= KEY_SWITCH_T1 && wParam < (KEY_SWITCH_T1 + TAGS)) { MinimizeTag(current_tag); current_tag = wParam - KEY_SWITCH_T1; ArrangeWindows(); break; } current = tags[current_tag].current_window; switch (wParam) { case KEY_SELECT_UP: if (current) { tags[current_tag].current_window = GetNextNode(); FocusCurrent(); } break; case KEY_SELECT_DOWN: if (current) { tags[current_tag].current_window = GetPreviousNode(); FocusCurrent(); } break; case KEY_MOVE_MAIN: SwapWindowWithNode(tags[current_tag].nodes); ArrangeWindows(); break; case KEY_EXIT: PostMessage(hwnd, WM_CLOSE, 0, 0); break; case KEY_MARGIN_LEFT: margin -= 20; ArrangeWindows(); break; case KEY_MARGIN_RIGHT: margin += 20; ArrangeWindows(); break; case KEY_IGNORE: if (!disableNext) { disableNext = 1; } else { disableNext = 0; } break; case KEY_MOUSE_LOCK: if (lockMouse) { lockMouse = 0; ClipCursor(0); } else { lockMouse = 1; FocusCurrent(); } break; case KEY_TILING_MODE: tags[current_tag].tilingMode = (tags[current_tag].tilingMode + 1) % 3; ArrangeWindows(); break; case KEY_MOVE_UP: if (current) { SwapWindowWithNode(GetNextNode()); ArrangeWindows(); } break; case KEY_MOVE_DOWN: if (current) { SwapWindowWithNode(GetPreviousNode()); ArrangeWindows(); } break; case KEY_DISP_CLASS: { LPSTR temp = (LPSTR)malloc(sizeof(TCHAR) * 128); GetClassName(GetForegroundWindow(), temp, 128); MessageBox(NULL, temp, "Window Class", MB_OK); free(temp); } break; case KEY_TILE: if (IsGoodWindow(GetForegroundWindow())) { AddNode(GetForegroundWindow(), current_tag); ArrangeWindows(); } break; case KEY_UNTILE: FullRemoveNode(GetForegroundWindow()); ArrangeWindows(); break; case KEY_INC_AREA: tags[current_tag].masterarea_count++; ArrangeWindows(); break; case KEY_DEC_AREA: tags[current_tag].masterarea_count--; ArrangeWindows(); break; case KEY_CLOSE_WIN: PostMessage(GetForegroundWindow(), WM_CLOSE, 0, 0); break; } break; case WM_TIMER: switch (wParam) { case TIMER_UPDATE_MOUSE: UpdateMousePos(hwnd); break; } break; default: if (msg == shellhookid) { // Handle the Shell Hook message switch (wParam) { case HSHELL_WINDOWCREATED: if (IsGoodWindow((HWND)lParam)) { AddNode((HWND)lParam, current_tag); ArrangeWindows(); FocusCurrent(); } break; case HSHELL_WINDOWDESTROYED: FullRemoveNode((HWND)lParam); ArrangeWindows(); FocusCurrent(); break; case HSHELL_WINDOWACTIVATED: { node *found = FindNode((HWND)lParam, current_tag); if (found) { tags[current_tag].current_window = current = found; FocusCurrent(); } } break; } } else { return DefWindowProc(hwnd, msg, wParam, lParam); } } return 0; }
// This does the actual tiling void ArrangeWindows() { int a, i, x, y, width, height; unsigned short masterarea_count; node *nodes; node *temp; a = CountNodes(); if (a == -1) return; i = 0; nodes = tags[current_tag].nodes; masterarea_count = tags[current_tag].masterarea_count; for (temp = nodes; temp; temp = temp->next) { RestoreWindow(temp->hwnd); if (a == 0) { // I think this is universal to all tiling modes x = 0; y = 0; width = screen_width; height = screen_height; } else { switch (tags[current_tag].tilingMode) { default: case MODE_VERTICAL: { if (i < masterarea_count) { x = 0; y = (screen_height / masterarea_count) * i; width = (screen_width / 2) + margin; height = (screen_height / masterarea_count); } else { x = (screen_width / 2) + margin; y = (screen_height / ((a + 1) - masterarea_count)) * (a - i); width = (screen_width / 2) - margin; height = (screen_height / ((a + 1) - masterarea_count)); } } break; case MODE_HORIZONTAL: { if (i < masterarea_count) { // Main window x = (screen_width / masterarea_count) * i; y = 0; width = (screen_width / masterarea_count); height = (screen_height / 2) + margin; } else { // Normal windows to be tiled x = (screen_width / ((a + 1) - masterarea_count)) * (a - i); y = (screen_height / 2) + margin; width = (screen_width / ((a + 1) - masterarea_count)); height = (screen_height / 2) - margin; } } break; case MODE_GRID: // See dvtm-license.txt { int ah, aw, rows, cols; for (cols = 0; cols <= (a + 1)/2; cols++) { if (cols * cols >= (a + 1)) { break; } } rows = (cols && (cols - 1) * cols >= (a + 1)) ? cols - 1 : cols; height = screen_height / (rows ? rows : 1); width = screen_width / (cols ? cols : 1); if (rows > 1 && i == (rows * cols) - cols && ((a + 1) - i) <= ((a + 1) % cols)) { width = screen_width / ((a + 1) - i); } x = (i % cols) * width; y = (i / cols) * height; ah = (i >= cols * (rows - 1)) ? screen_height - height * rows: 0; if (rows > 1 && i == (a + 1) - 1 && ((a + 1) - i) < ((a + 1) % cols)) { aw = screen_width - width * ((a + 1) % cols); } else { aw = ((i + 1) % cols == 0) ? screen_width - width * cols : 0; } width += aw; height += ah; } break; case MODE_FULLSCREEN: x = 0; y = 0; width = screen_width; height = screen_height; break; } } SetWindowPos(temp->hwnd, HWND_TOP, x + screen_x, y + screen_y, width, height, SWP_SHOWWINDOW); i++; } FocusCurrent(); }