/** @brief Shows the workspace menu on the screen @return void **/ void show_workspace_menu(Display *display, Window calling_widget, struct Workspace_list* workspaces , int index, int x, int y, struct Themes *themes) { int max_length = 100; for(int i = 0; i < workspaces->used_workspaces; i++) if(workspaces->list[i].workspace_menu.width > max_length) max_length = workspaces->list[i].workspace_menu.width; //If this is the title menu show the title of the window that the menu appeared on in bold. for(int i = 0; i < workspaces->used_workspaces; i++) { if(i == index) xcheck_raisewin(display, workspaces->list[i].workspace_menu.state[active]); else xcheck_raisewin(display, workspaces->list[i].workspace_menu.state[normal]); } //Make all the menu items the same width and height. for(int i = 0; i < workspaces->used_workspaces; i++) if(workspaces->list[i].workspace_menu.item) { //TODO menu_item_mid + lhs +rhs XMoveWindow(display, workspaces->list[i].workspace_menu.item , themes->popup_menu[popup_l_edge].w, themes->popup_menu[popup_t_edge].h + themes->popup_menu[menu_item_mid].h * i); XResizeWindow(display, workspaces->list[i].workspace_menu.item, max_length, themes->popup_menu[menu_item_mid].h); } workspaces->workspace_menu.inner_width = max_length; workspaces->workspace_menu.inner_height = themes->popup_menu[menu_item_mid].h * workspaces->used_workspaces; resize_popup_menu(display, &workspaces->workspace_menu, themes); place_popup_menu(display, calling_widget, workspaces->workspace_menu.widgets[popup_menu_parent].widget , x, y); }
/** @brief This function pops up the title menu in the titlebar or the window menu. This function is also the window menu, which is done by setting the index to -1. @return void @param index the index parameter is the window which was clicked, so that it can be shown in bold. **/ void show_title_menu(Display *display, struct Popup_menu *title_menu, Window calling_widget, struct Workspace* frames , int index, int x, int y, struct Themes *themes) { if(!frames) return; //TODO this does not consider what to do if a window is created when the menu is open int max_length = DEFAULT_MENU_ITEM_WIDTH; for(int i = 0; i < frames->used; i++) if(frames->list[i]->menu.width > max_length) { max_length = frames->list[i]->menu.width; } if(index == -1) for(int i = 0; i < frames->used; i++) { //TODO check that the tiled window can actually fit on the screen // if(frames->list[i].mode == tiling) xcheck_raisewin(display, frames->list[i].menu.state[inactive]); xcheck_raisewin(display, frames->list[i]->menu.state[normal]); } //If this is the title menu show the title of the window that the menu appeared on in bold. else for(int i = 0; i < frames->used; i++) { if(i == index) xcheck_raisewin(display, frames->list[i]->menu.state[active]); else xcheck_raisewin(display, frames->list[i]->menu.state[normal]); } //Make all the menu items the same width and height. for(int i = 0; i < frames->used; i++) { XMoveWindow(display, frames->list[i]->menu.item , themes->popup_menu[popup_l_edge].w, themes->popup_menu[popup_t_edge].h + themes->popup_menu[menu_item_mid].h * i); XResizeWindow(display, frames->list[i]->menu.item, max_length, themes->popup_menu[menu_item_mid].h); } //printf("Showing title menu at %d %d\n", x,y); title_menu->inner_width = max_length; title_menu->inner_height = themes->popup_menu[menu_item_mid].h * frames->used; XFlush(display); resize_popup_menu(display, title_menu, themes); place_popup_menu(display, calling_widget, title_menu->widgets[popup_menu_parent].widget, x, y); XFlush(display); }
void reset_frame_titlebar(Display *display, struct Frame *frame) { change_frame_widget_state(display, frame, frame_parent, normal); change_frame_widget_state(display, frame, close_button, normal); change_frame_widget_state(display, frame, title_menu_lhs, normal); change_frame_widget_state(display, frame, title_menu_text, normal); change_frame_widget_state(display, frame, title_menu_rhs, normal); change_frame_widget_state(display, frame, mode_dropdown_lhs, normal); change_frame_widget_state(display, frame, mode_dropdown_text, normal); change_frame_widget_state(display, frame, mode_dropdown_rhs, normal); xcheck_raisewin(display, frame->widgets[mode_dropdown_hotspot].widget); XFlush(display); }
/** @brief Changes the look of a frame's widget. It considers whether the window is already focussed when doing this. @return void **/ void change_frame_widget_state(Display* display, struct Frame* frame, enum Frame_widget widget, enum Widget_state state) { if(frame->focussed) { switch(state) { case normal: state = normal_focussed; break; case active: state = active_focussed; break; case normal_hover: state = normal_focussed_hover; break; case active_hover: state = active_focussed_hover; break; break; default: break; } } xcheck_raisewin(display, frame->widgets[widget].state[state]); XFlush(display); }
/** @brief This function pops up the mode menu on the specified active_frame @return void **/ void show_mode_menu(Display *display, Window calling_widget, struct Mode_menu *mode_menu , struct Frame *active_frame, int x, int y) { if(active_frame->mode == floating) xcheck_raisewin(display, mode_menu->items[floating].state[active]); else xcheck_raisewin(display, mode_menu->items[floating].state[normal]); if(active_frame->mode == tiling) xcheck_raisewin(display, mode_menu->items[tiling].state[active]); else xcheck_raisewin(display, mode_menu->items[tiling].state[normal]); if(active_frame->mode == desktop) xcheck_raisewin(display, mode_menu->items[desktop].state[active]); else xcheck_raisewin(display, mode_menu->items[desktop].state[normal]); xcheck_raisewin(display, mode_menu->items[hidden].state[normal]); XFlush(display); place_popup_menu(display, calling_widget, mode_menu->menu.widgets[popup_menu_parent].widget, x, y); }
/** @pre display is valid, menubar is not null but not initialized, seps is valid, themes is valid, cursors is valid. @post Menubar created and mapped. @brief This function uses the menubar member of the themes pointer to generate all the windows that comprise the menubar with appropriate pixmap backgrounds. @todo Possibly have an extra parameter that determines whether the menubar is a popup menu and use the shape extention. @return void **/ void create_menubar(Display *display, struct Menubar *menubar, struct Separators *seps, struct Themes *themes, struct Cursors *cursors) { /* create new window structure, using theme pixmaps */ XSetWindowAttributes set_attributes; Window root = DefaultRootWindow(display); Screen* screen = DefaultScreenOfDisplay(display); int black = BlackPixelOfScreen(screen); unsigned int spacing; spacing = (XWidthOfScreen(screen) - themes->menubar[program_menu].w )/4; menubar->widgets[menubar_parent].widget = XCreateSimpleWindow(display, root , 0, XHeightOfScreen(screen) - themes->menubar[menubar_parent].h, XWidthOfScreen(screen) , themes->menubar[menubar_parent].h, 0, black, black); xcheck_setpixmap(display, menubar->widgets[menubar_parent].widget , themes->menubar[menubar_parent].state_p[normal]); for(int i = 0; i < menubar_parent; i++) { menubar->widgets[i].widget = XCreateSimpleWindow(display, menubar->widgets[menubar_parent].widget , spacing*i, 0, themes->menubar[i].w, themes->menubar[i].h, 0, black, black); XSelectInput(display, menubar->widgets[i].widget, Button1MotionMask | ButtonPressMask | ButtonReleaseMask); XDefineCursor(display, menubar->widgets[i].widget, cursors->pressable); for(int j = 0; j <= inactive; j++) { if(themes->menubar[i].state_p[j]) { menubar->widgets[i].state[j] = XCreateSimpleWindow(display, menubar->widgets[i].widget , 0, 0, themes->menubar[i].w, themes->menubar[i].h, 0, black, black); char *label = NULL; char Program[] = "Program"; char Window[] = "Window"; char Options[] = "Options"; char Links[] = "Links"; char Tool[] = "Tool"; switch(i) { case program_menu: label = Program; break; case window_menu: label = Window; break; case options_menu: label = Options; break; case links_menu: label = Links; break; case tool_menu: label = Tool; break; } if(label) { create_text_background(display, menubar->widgets[i].state[j], label , &themes->font_theme[j], themes->menubar[i].state_p[j] , themes->menubar[i].w, themes->menubar[i].h); } else { xcheck_setpixmap(display, menubar->widgets[i].state[j], themes->menubar[i].state_p[j]); } xcheck_map(display, menubar->widgets[i].state[j]); } //else printf("Warning: Skipping state pixmap\n"); } xcheck_map(display, menubar->widgets[i].widget); } set_attributes.override_redirect = True; XChangeWindowAttributes(display, menubar->widgets[menubar_parent].widget , CWOverrideRedirect, &set_attributes); { XWindowChanges changes; unsigned int mask = CWSibling | CWStackMode; changes.stack_mode = Below; changes.sibling = seps->panel_separator; XConfigureWindow(display, menubar->widgets[menubar_parent].widget, mask, &changes); } /* Show initial state. */ xcheck_raisewin(display, menubar->widgets[program_menu].state[normal]); xcheck_raisewin(display, menubar->widgets[window_menu].state[normal]); XFlush(display); /* Show everything */ XMapWindow(display, menubar->widgets[menubar_parent].widget); XFlush(display); }
/** @brief create pixmaps with the specified name if it is available, otherwise use a default name @return void **/ void create_frame_name(Display* display, struct Popup_menu *window_menu, struct Frame *temp , struct Themes *themes, struct Atoms *atoms) { char untitled[] = "noname"; //struct Frame temp = *frame; Screen* screen = DefaultScreenOfDisplay(display); int black = BlackPixelOfScreen(screen); /* Destroy/Free old title if it had one */ free_frame_name(temp); { /* Recover EWMH UTF8 name first. If none exists, get the ICCCM ASCII name */ /* If this succeeds, previous names will be freed if they exists later on */ Atom ret_type; int ret_format; unsigned long ret_nitems; unsigned long ret_trailing_bytes; temp->window_name = NULL; if((XGetWindowProperty (display, temp->framed_window, atoms->name, (long)0, (long)MAX_WM_NAME_LENGTH , False, atoms->utf8 , &ret_type, &ret_format, &ret_nitems, &ret_trailing_bytes , (unsigned char **)&temp->window_name ) != Success) || temp->window_name == NULL) { //Try and get the non EWMH name if(!XFetchName(display, temp->framed_window, &temp->window_name)) { //Generate a blank name. printf("Warning: unnamed window\n"); XStoreName(display, temp->framed_window, untitled); XFlush(display); XFetchName(display, temp->framed_window, &temp->window_name); XFlush(display); } } } /* if(temp->window_name == NULL && frame->window_name != NULL && strcmp(frame->window_name, untitled) == 0) { //it was null and already has the name from untitled above. return; } else if( (temp->window_name != NULL && frame->window_name != NULL ) && (strcmp(temp->window_name, frame->window_name) == 0)) { XFree(temp->window_name); //skip this if the name hasn't changed return; } */ if(!temp->menu.item) { temp->menu.item = XCreateSimpleWindow(display , window_menu->widgets[popup_menu_parent].widget , themes->popup_menu[l_edge].w, 0 , XWidthOfScreen(screen), themes->popup_menu[menu_item_mid].h , 0, black, black); for(int i = 0; i <= inactive; i++) { temp->menu.state[i] = XCreateSimpleWindow(display , temp->menu.item , 0, 0 , XWidthOfScreen(screen), themes->popup_menu[menu_item_mid].h , 0, black, black); } XSelectInput(display, temp->menu.item, ButtonReleaseMask | EnterWindowMask | LeaveWindowMask); } temp->menu.width = get_text_width(display, temp->window_name, &themes->font_theme[active]); //create corresponding title menu item for this frame for(int i = 0; i <= inactive; i++) { XUnmapWindow(display, temp->menu.state[i]); XUnmapWindow(display, temp->widgets[title_menu_text].state[i]); XFlush(display); //create the title menu item with the windows title create_text_background(display, temp->menu.state[i], temp->window_name , &themes->font_theme[i], themes->popup_menu[menu_item_mid].state_p[i] , XWidthOfScreen(screen), themes->popup_menu[menu_item_mid].h); //TODO make the title for unfocussed windows not bold? create_text_background(display, temp->widgets[title_menu_text].state[i], temp->window_name , &themes->font_theme[active], themes->window_type[temp->theme_type][title_menu_text].state_p[i] , XWidthOfScreen(screen), themes->window_type[temp->theme_type][title_menu_text].h); //If this is mapped here, it might be shown in the wrong workspace, //XMapWindow(display, temp->menu.item); /* Show changes to background pixmaps */ XMapWindow(display, temp->menu.state[i]); XMapWindow(display, temp->widgets[title_menu_text].state[i]); } xcheck_raisewin(display, temp->menu.state[active]); //these are the items for inside the menu //need to create all these windows. { XWindowAttributes attr; XGetWindowAttributes(display, temp->menu.item, &attr); if(attr.map_state != IsUnmapped) { //remap all the state pixmaps XSelectInput(display, temp->menu.item, 0); XSync(display, False); XUnmapWindow(display, temp->menu.item); XSelectInput(display, temp->menu.item, ButtonReleaseMask | EnterWindowMask | LeaveWindowMask); XFlush(display); XMapWindow(display, temp->menu.item); } } XFlush(display); //*frame = temp; }