Beispiel #1
0
/**
@brief    Creates the mode menu which can be used by all windows in all workspaces.  The main even loop uses the windows and events to determine if a mode menu item was clicked or interacted with in some way.
@return   void
**/
void 
create_mode_menu(Display *display, struct Mode_menu *mode_menu
, struct Themes *themes, struct Cursors *cursors) {

  Screen* screen = DefaultScreenOfDisplay(display);
  int black = BlackPixelOfScreen(screen);

  mode_menu->menu.inner_width = DEFAULT_MENU_ITEM_WIDTH;
  mode_menu->menu.inner_height = themes->popup_menu[menu_item_mid].h * (hidden + 1);
  
  create_popup_menu(display, &mode_menu->menu, themes, cursors);

  //Create the menu items
  for(int i = 0; i <= hidden; i++) {

    mode_menu->items[i].item = XCreateSimpleWindow(display, mode_menu->menu.widgets[popup_menu_parent].widget
    , themes->popup_menu[popup_l_edge].w, themes->popup_menu[popup_t_edge].h + themes->popup_menu[menu_item_mid].h * i
    , mode_menu->menu.inner_width, themes->popup_menu[menu_item_mid].h, 0, black, black);

    XSelectInput(display, mode_menu->items[i].item,  ButtonReleaseMask | EnterWindowMask | LeaveWindowMask);
    for(int j = 0; j <= inactive; j++) {
      if(themes->popup_menu[i].state_p[j]) {
        char *label = NULL;
        char Floating[] = "Floating";
        char Tiling[] = "Tiling";
        char Hidden[] = "Hidden";
        char Desktop[] = "Desktop";

        switch(i) {
          case floating: label = Floating;
          break;
          case tiling: label = Tiling;
          break;
          case hidden: label = Hidden;
          break;
          case desktop: label = Desktop;
          break;
        }

        mode_menu->items[i].state[j] = XCreateSimpleWindow(display, mode_menu->items[i].item
        , 0, 0, mode_menu->menu.inner_width, themes->popup_menu[menu_item_mid].h, 0, black, black);

        create_text_background(display, mode_menu->items[i].state[j], label, &themes->font_theme[j]
        , themes->popup_menu[menu_item_mid].state_p[j]
        , themes->popup_menu[menu_item_mid].w, themes->popup_menu[menu_item_mid].h);
        XMapWindow(display, mode_menu->items[i].state[j]);
      }
//      else printf("Warning:  Skipping state pixmap\n");
    }
    XMapWindow(display, mode_menu->items[i].item);
  }

}
Beispiel #2
0
/**
@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);
}
Beispiel #3
0
/**
@brief    Creates a new workspace, including separators used for stacking windows in different modes and the workspace menu item for the program menu.
@return   the index of the created workspace
**/
int
create_workspace(Display *display, struct Workspace_list* workspaces, char *workspace_name, struct Themes *themes) {
//  Window root = DefaultRootWindow(display);
  Screen* screen =  DefaultScreenOfDisplay(display);
  int black = BlackPixelOfScreen(screen);
//  XSetWindowAttributes attributes;
  struct Workspace *frames;

  if(workspaces->list == NULL) {
    workspaces->used_workspaces = 0;
    workspaces->max_workspaces = 16;
    workspaces->list = malloc(sizeof(struct Workspace) * workspaces->max_workspaces);
    if(workspaces->list == NULL) return -1;
  }
  else if(workspaces->used_workspaces == workspaces->max_workspaces) {
    //printf("reallocating, used_workspaces %d, max%d\n", workspaces->used_workspaces, workspaces->max);
    struct Workspace* temp = NULL;
    temp = realloc(workspaces->list, sizeof(struct Workspace) * workspaces->max_workspaces * 2);
    if(temp != NULL) workspaces->list = temp;
    else {
      perror("\nError: Not enough available memory\n");
      return -1;
    }
    workspaces->max_workspaces *= 2;
  }

  //the frame list frames is the new workspace
  frames = &workspaces->list[workspaces->used_workspaces];
  frames->workspace_name = workspace_name;

  frames->states = calloc(sizeof(struct Saved_frame_state), workspaces->max_frames);
  if(!frames->states) { perror("Error: not enough memory to allocate frame save states in a new workspace"); return -1; }

  //TODO when a workspace is added to the list, it must also be resized to the width of that list.
  unsigned int width = workspaces->workspace_menu.inner_width;

  frames->workspace_menu.item = XCreateSimpleWindow(display
  , workspaces->workspace_menu.widgets[popup_menu_parent].widget
  , themes->popup_menu[popup_l_edge].w, themes->popup_menu[popup_t_edge].h
  , width, themes->popup_menu[menu_item_mid].h
  , 0, black, black);

  XSelectInput(display, frames->workspace_menu.item,  ButtonReleaseMask | EnterWindowMask | LeaveWindowMask);

  for(int i = 0; i <= inactive; i++) { //if(themes->popup_menu[menu_item].state_p[i])
    frames->workspace_menu.state[i] = XCreateSimpleWindow(display
    , frames->workspace_menu.item
    , 0, 0
    , XWidthOfScreen(screen), themes->popup_menu[menu_item_mid].h
    , 0, black, black);

    create_text_background(display, frames->workspace_menu.state[i], frames->workspace_name
    , &themes->font_theme[i], themes->popup_menu[menu_item_mid].state_p[i]
    , themes->popup_menu[menu_item_mid].w, themes->popup_menu[menu_item_mid].h);

    XMapWindow(display, frames->workspace_menu.state[i]);
  }

  XMapWindow(display, frames->workspace_menu.item);

  frames->workspace_menu.width = get_text_width(display, frames->workspace_name, &themes->font_theme[active]);

  //Create the frame_list
  frames->used = 0;
  frames->max  = DEFAULT_STARTING_FRAMES;
  frames->list = NULL; //this is allocated when we change to this workspace.

  frames->focus.used = 0;
  frames->focus.max  = 8; //must be divisible by 2
  frames->focus.list = malloc(sizeof(struct Focus_list) * frames->focus.max); //ok if it fails.
  #ifdef SHOW_WORKSPACE
  printf("Created workspace %d\n", workspaces->used_workspaces);
  #endif

  //need to make the existing neutral windows available to new workspaces
  for(int i = 0; i < workspaces->used_frames; i++) {
    if(suitable_for_foreign_workspaces(&workspaces->frame_list[i])) {
      load_initial_states(&frames->states[i], &workspaces->frame_list[i]);
    }
  }

  workspaces->used_workspaces++;
  XSync(display, False);

  return workspaces->used_workspaces - 1;
}
Beispiel #4
0
/**
@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;
}