コード例 #1
0
ファイル: Menu.C プロジェクト: bbidulock/flwm
void
ShowTabMenu(int tab)
{

  static char beenhere;
  if (!beenhere) {
    beenhere = 1;
#if FL_MAJOR_VERSION < 2
    Fl::set_labeltype(FRAME_LABEL, frame_label_draw, frame_label_measure);
    Fl::set_labeltype(TEXT_LABEL, label_draw, label_measure);
#endif
    if (exit_flag) {
      Fl_Menu_Item* m = other_menu_items+num_other_items-2;
      m->label("Exit");
      m->callback(exit_cb);
    }
  }

  static Fl_Menu_Item* menu = 0;
  static int arraysize = 0;

#if DESKTOPS
  int one_desktop = !Desktop::first->next;
#endif

  // count up how many items are on the menu:

  int n = num_other_items;
#if WMX_MENU_ITEMS
  load_wmx();
  if (num_wmx) {
    n -= 1; // delete "new xterm"
    // add wmx items
    int	level = 0;
    for (int i=0; i<num_wmx; i++) {
      int nextlev = (i==num_wmx-1)?0:strspn(wmxlist[i+1], "/")-1;
      if (nextlev < level) {
	n += level-nextlev;
	level = nextlev;
      } else if (nextlev > level)
	level++;
      n++;
    }
  }
#endif

#if DESKTOPS
  // count number of items per desktop in these variables:
  int numsticky = 0;
  Desktop* d;
  for (d = Desktop::first; d; d = d->next) d->junk = 0;
#endif

  // every frame contributes 1 item:
  Frame* c;
  for (c = Frame::first; c; c = c->next) {
    if (c->state() == UNMAPPED || c->transient_for()) continue;
#if DESKTOPS
    if (!c->desktop()) {
      numsticky++;
    } else {
      c->desktop()->junk++;
    }
#endif
    n++;
  }

#if DESKTOPS
  if (!one_desktop) {
    // add the sticky "desktop":
    n += 2; if (!numsticky) n++;
    if (Desktop::current()) {
      n += numsticky;
      Desktop::current()->junk += numsticky;
    }
    // every desktop contributes menu title, null terminator,
    // and possible delete:
    for (d = Desktop::first; d; d = d->next) {
      n += 2; if (!d->junk) n++;
    }
  }
#endif

  if (n > arraysize) {
    delete[] menu;
    menu = new Fl_Menu_Item[arraysize = n];
  }

  // build the menu:
  n = 0;
  const Fl_Menu_Item* preset = 0;
  const Fl_Menu_Item* first_on_desk = 0;
#if DESKTOPS
  if (one_desktop) {
#endif
    for (c = Frame::first; c; c = c->next) {
      if (c->state() == UNMAPPED || c->transient_for()) continue;
#if FL_MAJOR_VERSION < 2
      init(menu[n],(char*)c);
      menu[n].labeltype(FRAME_LABEL);
#else
      init(menu[n],c->label());
#endif
      menu[n].callback(frame_callback, c);
      if (is_active_frame(c)) preset = menu+n;
      n++;
    }
    if (n > 0) first_on_desk = menu;
#if DESKTOPS
  } else for (d = Desktop::first; ; d = d->next) {
    // this loop adds the "sticky" desktop last, when d==0
    if (d == Desktop::current()) preset = menu+n;
    init(menu[n], d ? d->name() : "Sticky");
    menu[n].callback(desktop_cb, d);
    menu[n].flags = FL_SUBMENU;
    n++;
    if (d && !d->junk) {
      init(menu[n],"delete this desktop");
      menu[n].callback(delete_desktop_cb, d);
      n++;
    } else if (!d && !numsticky) {
      init(menu[n],"(empty)");
      menu[n].callback_ = 0;
      menu[n].deactivate();
      n++;
    } else {
      if (d == Desktop::current()) first_on_desk = menu+n;
      for (c = Frame::first; c; c = c->next) {
	if (c->state() == UNMAPPED || c->transient_for()) continue;
	if (c->desktop() == d || (!c->desktop() && d == Desktop::current())) {
	  init(menu[n],(char*)c);
#if FL_MAJOR_VERSION < 2
	  init(menu[n],(char*)c);
	  menu[n].labeltype(FRAME_LABEL);
#else
	  init(menu[n],c->label());
#endif
	  menu[n].callback(d == Desktop::current() ?
			   frame_callback : move_frame_callback, c);
	  if (d == Desktop::current() && is_active_frame(c)) preset = menu+n;
	  n++;
	}
      }
    }
    menu[n].label(0); n++; // terminator for submenu
    if (!d) break;
  }
#endif

  // For ALT+Tab, move the selection forward or backward:
  if (tab > 0 && first_on_desk) {
    if (!preset)
      preset = first_on_desk;
    else {
      preset++;
      if (!preset->label() || preset->callback_ != frame_callback)
	preset = first_on_desk;
    }
  } else if (tab < 0 && first_on_desk) {
    if (preset && preset != first_on_desk)
      preset--;
    else {
      // go to end of menu
      preset = first_on_desk;
      while (preset[1].label() && preset[1].callback_ == frame_callback)
	preset++;
    }
  }

#if WMX_MENU_ITEMS
  // put wmx-style commands above that:
  if (num_wmx > 0) {
    char* cmd;
    int pathlen[MAX_NESTING_DEPTH];
    int level = 0;
    pathlen[0] = wmx_pathlen;
    for (int i = 0; i < num_wmx; i++) {
      cmd = wmxlist[i];
      cmd += strspn(cmd, "/")-1;
      init(menu[n], cmd+pathlen[level]);
#if FL_MAJOR_VERSION < 2
#if DESKTOPS
      if (one_desktop)
#endif
	if (!level)
	  menu[n].labeltype(TEXT_LABEL);
#endif
      int nextlev = (i==num_wmx-1)?0:strspn(wmxlist[i+1], "/")-1;
      if (nextlev < level) {
	menu[n].callback(spawn_cb, cmd);
	// Close 'em off
	for (; level>nextlev; level--)
	  init(menu[++n], 0);
      } else if (nextlev > level) {
	// This should be made a submenu
	pathlen[++level] = strlen(cmd)+1; // extra for next trailing /
	menu[n].flags = FL_SUBMENU;
	menu[n].callback((Fl_Callback*)0);
      } else {
	menu[n].callback(spawn_cb, cmd);
      }
      n++;
    }
  }

  // put the fixed menu items at the bottom:
#if XTERM_MENU_ITEM
  if (num_wmx) // if wmx commands, delete the built-in xterm item:
    memcpy(menu+n, other_menu_items+1, sizeof(other_menu_items)-sizeof(Fl_Menu_Item));
  else
#endif
#endif
    memcpy(menu+n, other_menu_items, sizeof(other_menu_items));
#if FL_MAJOR_VERSION < 2
#if DESKTOPS
  if (one_desktop)
#endif
    // fix the menus items so they are indented to align with window names:
    while (menu[n].label()) menu[n++].labeltype(TEXT_LABEL);
#endif

  const Fl_Menu_Item* picked =
    menu->popup(Fl::event_x(), Fl::event_y(), 0, preset);
#if FL_MAJOR_VERSION < 2
  if (picked && picked->callback()) picked->do_callback(0);
#endif
}