/** Run a menu action. */ void RunTaskBarCommand(MenuAction *action, unsigned button) { ClientEntry *cp; if(action->type & MA_GROUP_MASK) { TaskEntry *tp = action->context; for(cp = tp->clients; cp; cp = cp->next) { if(!ShouldFocus(cp->client, 0)) { continue; } switch(action->type & ~MA_GROUP_MASK) { case MA_SENDTO: SetClientDesktop(cp->client, action->value); break; case MA_CLOSE: DeleteClient(cp->client); break; case MA_RESTORE: RestoreClient(cp->client, 0); break; case MA_MINIMIZE: MinimizeClient(cp->client, 0); break; default: break; } } } else if(action->type == MA_EXECUTE) { if(button == Button3) { Window w; int x, y; GetMousePosition(&x, &y, &w); ShowWindowMenu(action->context, x, y, 0); } else { ClientNode *np = action->context; RestoreClient(np, 1); FocusClient(np); MoveMouse(np->window, np->width / 2, np->height / 2); } } else { RunWindowCommand(action, button); } }
/** Process a key press event. */ void HandleKeyPress(const XKeyEvent *event) { ClientNode *np; KeyType key; SetMousePosition(event->x_root, event->y_root, event->window); key = GetKey(event); np = GetActiveClient(); switch(key & 0xFF) { case KEY_EXEC: RunKeyCommand(event); break; case KEY_DESKTOP: ChangeDesktop((key >> 8) - 1); break; case KEY_RDESKTOP: RightDesktop(); break; case KEY_LDESKTOP: LeftDesktop(); break; case KEY_UDESKTOP: AboveDesktop(); break; case KEY_DDESKTOP: BelowDesktop(); break; case KEY_SHOWDESK: ShowDesktop(); break; case KEY_SHOWTRAY: ShowAllTrays(); break; case KEY_NEXT: StartWindowWalk(); FocusNext(); break; case KEY_NEXTSTACK: StartWindowStackWalk(); WalkWindowStack(1); break; case KEY_PREV: StartWindowWalk(); FocusPrevious(); break; case KEY_PREVSTACK: StartWindowStackWalk(); WalkWindowStack(0); break; case KEY_CLOSE: if(np) { DeleteClient(np); } break; case KEY_SHADE: if(np) { if(np->state.status & STAT_SHADED) { UnshadeClient(np); } else { ShadeClient(np); } } break; case KEY_STICK: if(np) { if(np->state.status & STAT_STICKY) { SetClientSticky(np, 0); } else { SetClientSticky(np, 1); } } break; case KEY_MOVE: if(np) { MoveClientKeyboard(np); } break; case KEY_RESIZE: if(np) { ResizeClientKeyboard(np); } break; case KEY_MIN: if(np) { MinimizeClient(np, 1); } break; case KEY_MAX: if(np) { if(np->state.maxFlags) { MaximizeClient(np, MAX_NONE); } else { MaximizeClient(np, MAX_HORIZ | MAX_VERT); } } break; case KEY_MAXTOP: ToggleMaximized(np, MAX_TOP | MAX_HORIZ); break; case KEY_MAXBOTTOM: ToggleMaximized(np, MAX_BOTTOM | MAX_HORIZ); break; case KEY_MAXLEFT: ToggleMaximized(np, MAX_LEFT | MAX_VERT); break; case KEY_MAXRIGHT: ToggleMaximized(np, MAX_RIGHT | MAX_VERT); break; case KEY_MAXV: ToggleMaximized(np, MAX_VERT); break; case KEY_MAXH: ToggleMaximized(np, MAX_HORIZ); break; case KEY_ROOT: ShowKeyMenu(event); break; case KEY_WIN: if(np) { RaiseClient(np); ShowWindowMenu(np, np->x, np->y, 1); } break; case KEY_RESTART: Restart(); break; case KEY_EXIT: Exit(); break; case KEY_FULLSCREEN: if(np) { if(np->state.status & STAT_FULLSCREEN) { SetClientFullScreen(np, 0); } else { SetClientFullScreen(np, 1); } } break; case KEY_SENDR: if(np) { SetClientDesktop(np, GetRightDesktop(np->state.desktop)); } break; case KEY_SENDL: if(np) { SetClientDesktop(np, GetLeftDesktop(np->state.desktop)); } break; case KEY_SENDU: if(np) { SetClientDesktop(np, GetAboveDesktop(np->state.desktop)); } break; case KEY_SENDD: if(np) { SetClientDesktop(np, GetBelowDesktop(np->state.desktop)); } break; default: break; } DiscardEnterEvents(); }
/** Take the appropriate action for a click on a client border. */ void DispatchBorderButtonEvent(const XButtonEvent *event, ClientNode *np) { static Time lastClickTime = 0; static int lastX = 0, lastY = 0; static char doubleClickActive = 0; BorderActionType action; int bsize; /* Middle click starts a move unless it's over the maximize button. */ action = GetBorderActionType(np, event->x, event->y); if(event->button == Button2 && action != BA_MAXIMIZE) { MoveClient(np, event->x, event->y); return; } /* Determine the size of the border. */ if(np->state.border & BORDER_OUTLINE) { bsize = settings.borderWidth; } else { bsize = 0; } /* Other buttons are context sensitive. */ switch(action & 0x0F) { case BA_RESIZE: /* Border */ if(event->type == ButtonPress) { if(event->button == Button1) { ResizeClient(np, action, event->x, event->y); } else if(event->button == Button3) { const int x = np->x + event->x - bsize; const int y = np->y + event->y - settings.titleHeight - bsize; ShowWindowMenu(np, x, y, 0); } } break; case BA_MOVE: /* Title bar */ if(event->button == Button1) { if(event->type == ButtonPress) { if(doubleClickActive && event->time != lastClickTime && event->time - lastClickTime <= settings.doubleClickSpeed && abs(event->x - lastX) <= settings.doubleClickDelta && abs(event->y - lastY) <= settings.doubleClickDelta) { MaximizeClientDefault(np); doubleClickActive = 0; } else { if(MoveClient(np, event->x, event->y)) { doubleClickActive = 0; } else { doubleClickActive = 1; lastClickTime = event->time; lastX = event->x; lastY = event->y; } } } } else if(event->button == Button3) { const int x = np->x + event->x - bsize; const int y = np->y + event->y - settings.titleHeight - bsize; ShowWindowMenu(np, x, y, 0); } else if(event->button == Button4) { ShadeClient(np); } else if(event->button == Button5) { UnshadeClient(np); } break; case BA_MENU: /* Menu button */ if(event->button == Button4) { ShadeClient(np); } else if(event->button == Button5) { UnshadeClient(np); } else if(event->type == ButtonPress) { const int x = np->x + event->x - bsize; const int y = np->y + event->y - settings.titleHeight - bsize; ShowWindowMenu(np, x, y, 0); } break; case BA_CLOSE: /* Close button */ if(event->type == ButtonRelease && (event->button == Button1 || event->button == Button3)) { DeleteClient(np); } break; case BA_MAXIMIZE: /* Maximize button */ if(event->type == ButtonRelease) { switch(event->button) { case Button1: MaximizeClientDefault(np); break; case Button2: MaximizeClient(np, np->state.maxFlags ^ MAX_VERT); break; case Button3: MaximizeClient(np, np->state.maxFlags ^ MAX_HORIZ); break; default: break; } } break; case BA_MINIMIZE: /* Minimize button */ if(event->type == ButtonRelease) { if(event->button == Button3) { if(np->state.status & STAT_SHADED) { UnshadeClient(np); } else { ShadeClient(np); } } else if(event->button == Button1) { MinimizeClient(np, 1); } } break; default: break; } DiscardEnterEvents(); }
/** Process a key press event. */ void HandleKeyPress(const XKeyEvent *event) { ClientNode *np; KeyType key; key = GetKey(event); np = GetActiveClient(); switch(key & 0xFF) { case KEY_EXEC: RunKeyCommand(event); break; case KEY_DESKTOP: ChangeDesktop((key >> 8) - 1); break; case KEY_RDESKTOP: RightDesktop(); break; case KEY_LDESKTOP: LeftDesktop(); break; case KEY_UDESKTOP: AboveDesktop(); break; case KEY_DDESKTOP: BelowDesktop(); break; case KEY_SHOWDESK: ShowDesktop(); break; case KEY_SHOWTRAY: ShowAllTrays(); break; case KEY_NEXT: StartWindowWalk(); FocusNext(); break; case KEY_NEXTSTACK: StartWindowStackWalk(); WalkWindowStack(1); break; case KEY_PREV: StartWindowWalk(); FocusPrevious(); break; case KEY_PREVSTACK: StartWindowStackWalk(); WalkWindowStack(0); break; case KEY_CLOSE: if(np) { DeleteClient(np); } break; case KEY_SHADE: if(np) { if(np->state.status & STAT_SHADED) { UnshadeClient(np); } else { ShadeClient(np); } } break; case KEY_STICK: if(np) { if(np->state.status & STAT_STICKY) { SetClientSticky(np, 0); } else { SetClientSticky(np, 1); } } break; case KEY_MOVE: if(np) { MoveClientKeyboard(np); } break; case KEY_RESIZE: if(np) { ResizeClientKeyboard(np); } break; case KEY_MIN: if(np) { MinimizeClient(np, 1); } break; case KEY_MAX: if(np) { MaximizeClient(np, 1, 1); } break; case KEY_ROOT: ShowKeyMenu(event); break; case KEY_WIN: if(np) { ShowWindowMenu(np, np->x, np->y); } break; case KEY_RESTART: Restart(); break; case KEY_EXIT: Exit(); break; case KEY_FULLSCREEN: if(np) { if(np->state.status & STAT_FULLSCREEN) { SetClientFullScreen(np, 0); } else { SetClientFullScreen(np, 1); } } break; case KEY_SENDR: if(np) { SetClientDesktop(np, GetRightDesktop(np->state.desktop)); } break; case KEY_SENDL: if(np) { SetClientDesktop(np, GetLeftDesktop(np->state.desktop)); } break; case KEY_SENDU: if(np) { SetClientDesktop(np, GetAboveDesktop(np->state.desktop)); } break; case KEY_SENDD: if(np) { SetClientDesktop(np, GetBelowDesktop(np->state.desktop)); } break; default: break; } }
/** Process a button event. */ void HandleButtonEvent(const XButtonEvent *event) { int x, y; ClientNode *np; int north, south, east, west; np = FindClientByParent(event->window); if(np) { RaiseClient(np); if(focusModel == FOCUS_CLICK) { FocusClient(np); } switch(event->button) { case Button1: DispatchBorderButtonEvent(event, np); break; case Button2: MoveClient(np, event->x, event->y); break; case Button3: GetBorderSize(np, &north, &south, &east, &west); x = event->x + np->x - west; y = event->y + np->y - north; ShowWindowMenu(np, x, y); break; case Button4: ShadeClient(np); break; case Button5: UnshadeClient(np); break; default: break; } } else if(event->window == rootWindow && event->type == ButtonPress) { if(!ShowRootMenu(event->button, event->x, event->y)) { if(event->button == 4) { LeftDesktop(); } else if(event->button == 5) { RightDesktop(); } } } else { np = FindClientByWindow(event->window); if(np) { switch(event->button) { case Button1: case Button2: RaiseClient(np); if(focusModel == FOCUS_CLICK) { FocusClient(np); } if(event->state & Mod1Mask) { GetBorderSize(np, &north, &south, &east, &west); MoveClient(np, event->x + west, event->y + north); } break; case Button3: if(event->state & Mod1Mask) { GetBorderSize(np, &north, &south, &east, &west); ResizeClient(np, BA_RESIZE | BA_RESIZE_E | BA_RESIZE_S, event->x + west, event->y + north); } else { RaiseClient(np); if(focusModel == FOCUS_CLICK) { FocusClient(np); } } break; default: break; } JXAllowEvents(display, ReplayPointer, CurrentTime); } } UpdatePager(); }
/** Take the appropriate action for a click on a client border. */ void DispatchBorderButtonEvent(const XButtonEvent *event, ClientNode *np) { static Time lastClickTime = 0; static int lastX = 0, lastY = 0; static int doubleClickActive = 0; BorderActionType action; int bsize; action = GetBorderActionType(np, event->x, event->y); switch(action & 0x0F) { case BA_RESIZE: if(event->type == ButtonPress) { ResizeClient(np, action, event->x, event->y); } break; case BA_MOVE: if(event->type == ButtonPress) { if(doubleClickActive && abs(event->time - lastClickTime) > 0 && abs(event->time - lastClickTime) <= doubleClickSpeed && abs(event->x - lastX) <= doubleClickDelta && abs(event->y - lastY) <= doubleClickDelta) { MaximizeClientDefault(np); doubleClickActive = 0; } else { if(MoveClient(np, event->x, event->y)) { doubleClickActive = 0; } else { doubleClickActive = 1; lastClickTime = event->time; lastX = event->x; lastY = event->y; } } } break; case BA_MENU: if(event->type == ButtonPress) { if(np->state.border & BORDER_OUTLINE) { bsize = borderWidth; } else { bsize = 0; } ShowWindowMenu(np, np->x + event->x - bsize, np->y + event->y - titleHeight - bsize); } break; case BA_CLOSE: if(event->type == ButtonRelease) { DeleteClient(np); } break; case BA_MAXIMIZE: if(event->type == ButtonRelease) { MaximizeClientDefault(np); } break; case BA_MINIMIZE: if(event->type == ButtonRelease) { MinimizeClient(np); } break; default: break; } }