From a041d9898e6d699bd8c0c25482ec574feb03c547 Mon Sep 17 00:00:00 2001 From: "John Ankarstr\\xf6m" Date: Sat, 29 May 2021 12:54:47 +0200 Subject: First commit This is the original state of the released tarball for JWM 1.8, which will serve as my starting point for further modifications. --- src/winmenu.c | 327 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 327 insertions(+) create mode 100644 src/winmenu.c (limited to 'src/winmenu.c') diff --git a/src/winmenu.c b/src/winmenu.c new file mode 100644 index 0000000..7b537cc --- /dev/null +++ b/src/winmenu.c @@ -0,0 +1,327 @@ +/**************************************************************************** + * Functions for handling window menus. + * Copyright (C) 2004 Joe Wingbermuehle + ****************************************************************************/ + +#include "jwm.h" +#include "winmenu.h" +#include "client.h" +#include "menu.h" +#include "main.h" +#include "desktop.h" +#include "move.h" +#include "resize.h" +#include "event.h" +#include "cursor.h" +#include "misc.h" + +static const char *SENDTO_TEXT = "Send To"; +static const char *LAYER_TEXT = "Layer"; + +static Menu *CreateWindowMenu(); +static void RunWindowCommand(const MenuAction *action); + +static void CreateWindowLayerMenu(Menu *menu); +static void CreateWindowSendToMenu(Menu *menu); +static void AddWindowMenuItem(Menu *menu, const char *name, + MenuActionType type, int value); + +static ClientNode *client = NULL; + +/**************************************************************************** + ****************************************************************************/ +void GetWindowMenuSize(ClientNode *np, int *width, int *height) { + + Menu *menu; + + client = np; + menu = CreateWindowMenu(); + InitializeMenu(menu); + *width = menu->width; + *height = menu->height; + DestroyMenu(menu); + +} + +/**************************************************************************** + ****************************************************************************/ +void ShowWindowMenu(ClientNode *np, int x, int y) { + + Menu *menu; + + client = np; + menu = CreateWindowMenu(); + + InitializeMenu(menu); + + ShowMenu(menu, RunWindowCommand, x, y); + + DestroyMenu(menu); + +} + +/**************************************************************************** + ****************************************************************************/ +Menu *CreateWindowMenu() { + + Menu *menu; + + menu = Allocate(sizeof(Menu)); + menu->itemHeight = 0; + menu->items = NULL; + menu->label = NULL; + + /* Note that items are added in reverse order of display. */ + + if(!(client->state.status & STAT_WMDIALOG)) { + AddWindowMenuItem(menu, "Close", MA_CLOSE, 0); + AddWindowMenuItem(menu, "Kill", MA_KILL, 0); + AddWindowMenuItem(menu, NULL, MA_NONE, 0); + } + + if(client->state.status & (STAT_MAPPED | STAT_SHADED)) { + if(client->state.border & BORDER_RESIZE) { + AddWindowMenuItem(menu, "Resize", MA_RESIZE, 0); + } + if(client->state.border & BORDER_MOVE) { + AddWindowMenuItem(menu, "Move", MA_MOVE, 0); + } + } + + if(client->state.border & BORDER_MIN) { + + if(client->state.status & STAT_MINIMIZED) { + AddWindowMenuItem(menu, "Restore", MA_RESTORE, 0); + } else { + if(client->state.status & STAT_SHADED) { + AddWindowMenuItem(menu, "Unshade", MA_SHADE, 0); + } else { + AddWindowMenuItem(menu, "Shade", MA_SHADE, 0); + } + AddWindowMenuItem(menu, "Minimize", MA_MINIMIZE, 0); + } + + } + + if((client->state.border & BORDER_MAX) + && (client->state.status & STAT_MAPPED)) { + + AddWindowMenuItem(menu, "Maximize", MA_MAXIMIZE, 0); + } + + if(!(client->state.status & STAT_WMDIALOG)) { + + if(client->state.status & STAT_STICKY) { + AddWindowMenuItem(menu, "Unstick", MA_STICK, 0); + } else { + AddWindowMenuItem(menu, "Stick", MA_STICK, 0); + } + + CreateWindowLayerMenu(menu); + + if(!(client->state.status & STAT_STICKY)) { + CreateWindowSendToMenu(menu); + } + + } + + return menu; +} + +/**************************************************************************** + ****************************************************************************/ +void CreateWindowLayerMenu(Menu *menu) { + + Menu *submenu; + MenuItem *item; + char str[10]; + unsigned int x; + + item = Allocate(sizeof(MenuItem)); + item->type = MENU_ITEM_SUBMENU; + item->name = CopyString(LAYER_TEXT); + item->action.type = MA_NONE; + item->action.data.str = NULL; + item->iconName = NULL; + + item->next = menu->items; + menu->items = item; + + submenu = Allocate(sizeof(Menu)); + item->submenu = submenu; + submenu->itemHeight = 0; + submenu->items = NULL; + submenu->label = NULL; + + if(client->state.layer == LAYER_TOP) { + AddWindowMenuItem(submenu, "[Top]", MA_LAYER, LAYER_TOP); + } else { + AddWindowMenuItem(submenu, "Top", MA_LAYER, LAYER_TOP); + } + + str[4] = 0; + for(x = LAYER_TOP - 1; x > LAYER_BOTTOM; x--) { + if(x == LAYER_NORMAL) { + if(client->state.layer == x) { + AddWindowMenuItem(submenu, "[Normal]", MA_LAYER, x); + } else { + AddWindowMenuItem(submenu, "Normal", MA_LAYER, x); + } + } else { + if(client->state.layer == x) { + str[0] = '['; + str[3] = ']'; + } else { + str[0] = ' '; + str[3] = ' '; + } + if(x < 10) { + str[1] = ' '; + } else { + str[1] = (x / 10) + '0'; + } + str[2] = (x % 10) + '0'; + AddWindowMenuItem(submenu, str, MA_LAYER, x); + } + } + + if(client->state.layer == LAYER_BOTTOM) { + AddWindowMenuItem(submenu, "[Bottom]", MA_LAYER, LAYER_BOTTOM); + } else { + AddWindowMenuItem(submenu, "Bottom", MA_LAYER, LAYER_BOTTOM); + } + +} + +/**************************************************************************** + ****************************************************************************/ +void CreateWindowSendToMenu(Menu *menu) { + + unsigned int mask; + unsigned int x; + + mask = 0; + for(x = 0; x < desktopCount; x++) { + if(client->state.desktop == x + || (client->state.status & STAT_STICKY)) { + mask |= 1 << x; + } + } + + AddWindowMenuItem(menu, SENDTO_TEXT, MA_NONE, 0); + + /* Now the first item in the menu is for the desktop list. */ + menu->items->submenu = CreateDesktopMenu(mask); + +} + +/**************************************************************************** + ****************************************************************************/ +void AddWindowMenuItem(Menu *menu, const char *name, + MenuActionType type, int value) { + + MenuItem *item; + + item = Allocate(sizeof(MenuItem)); + if(name) { + item->type = MENU_ITEM_NORMAL; + } else { + item->type = MENU_ITEM_SEPARATOR; + } + item->name = CopyString(name); + item->action.type = type; + item->action.data.i = value; + item->iconName = NULL; + item->submenu = NULL; + + item->next = menu->items; + menu->items = item; + +} + +/**************************************************************************** + ****************************************************************************/ +void ChooseWindow(const MenuAction *action) { + + XEvent event; + ClientNode *np; + + GrabMouseForChoose(); + + for(;;) { + + WaitForEvent(&event); + + if(event.type == ButtonPress) { + if(event.xbutton.button == Button1) { + np = FindClientByWindow(event.xbutton.subwindow); + if(np) { + client = np; + RunWindowCommand(action); + } + } + break; + } else if(event.type == KeyPress) { + break; + } + + } + + JXUngrabPointer(display, CurrentTime); + +} + +/**************************************************************************** + ****************************************************************************/ +void RunWindowCommand(const MenuAction *action) { + + switch(action->type) { + case MA_STICK: + if(client->state.status & STAT_STICKY) { + SetClientSticky(client, 0); + } else { + SetClientSticky(client, 1); + } + break; + case MA_MAXIMIZE: + MaximizeClient(client); + break; + case MA_MINIMIZE: + MinimizeClient(client); + break; + case MA_RESTORE: + RestoreClient(client, 1); + break; + case MA_CLOSE: + DeleteClient(client); + break; + case MA_SENDTO: + case MA_DESKTOP: + SetClientDesktop(client, action->data.i); + break; + case MA_SHADE: + if(client->state.status & STAT_SHADED) { + UnshadeClient(client); + } else { + ShadeClient(client); + } + break; + case MA_MOVE: + MoveClientKeyboard(client); + break; + case MA_RESIZE: + ResizeClientKeyboard(client); + break; + case MA_KILL: + KillClient(client); + break; + case MA_LAYER: + SetClientLayer(client, action->data.i); + break; + default: + Debug("unknown window command: %d", action->type); + break; + } + +} + -- cgit v1.2.3