Logo Search packages:      
Sourcecode: matchbox-window-manager version File versions  Download package

main_client.c

/* 
 *  Matchbox Window Manager - A lightweight window manager not for the
 *                            desktop.
 *
 *  Authored By Matthew Allum <mallum@o-hand.com>
 *
 *  Copyright (c) 2002, 2004 OpenedHand Ltd - http://o-hand.com
 *
 *  This program is free software; you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License as published by
 *  the Free Software Foundation; either version 2, or (at your option)
 *  any later version.
 *
 *  This program is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU General Public License for more details.
 *
 */
#include "main_client.h"

Client*
main_client_new(Wm *w, Window win)
{
   Client *c = base_client_new(w, win); 

   if (!c) return NULL;
   
   c->type = MBCLIENT_TYPE_APP;
   c->reparent     = &main_client_reparent;
   c->redraw       = &main_client_redraw;
   c->button_press = &main_client_button_press;
   c->move_resize  = &main_client_move_resize;
   c->get_coverage = &main_client_get_coverage;
   c->hide         = &main_client_hide;
   c->show         = &main_client_show;
   c->configure    = &main_client_configure;
   c->destroy      = &main_client_destroy;
   c->iconize      = &main_client_iconize;

   main_client_check_for_state_hints(c);

   main_client_check_for_single(c);
   
   return c;
}

void
main_client_check_for_state_hints(Client *c)
{
  dbg("%s() checking for fullscreen hint\n", __func__);

  if (ewmh_state_check(c, c->wm->atoms[WINDOW_STATE_FULLSCREEN]))
    {
      c->flags ^= CLIENT_FULLSCREEN_FLAG;
      dbg("%s() client is fullscreen\n", __func__);
    }
}

void
main_client_check_for_single(Client *c)
{
  Wm     *w = c->wm;

  if (w->flags & SINGLE_FLAG)
    {
      /* There was only main client till this came along */
      w->flags ^= SINGLE_FLAG; /* turn off single flag */
      if (w->stack_top_app)
      main_client_redraw(w->stack_top_app, False); /* update menu button */
    } else if (!w->stack_top_app) /* This must be the only client*/
      c->wm->flags |= SINGLE_FLAG; /* so turn on single flag */      
}

/* Handle the case for showing input methods ( toolbars ) 
 * for fullscreen 
 */
int
main_client_manage_toolbars_for_fullscreen(Client *c, Bool main_client_showing)
{
#ifdef USE_ALT_INPUT_WIN
  Wm     *w = c->wm;
  Client *p  = NULL;

  dbg("%s() called\n", __func__);

  stack_enumerate(w, p)
    {
      if (p->type == MBCLIENT_TYPE_DIALOG)
      {
        if (p->flags & CLIENT_TB_ALT_TRANS_FOR_APP 
            && p->trans == c)
          {
            toolbar_client_configure(p);
            toolbar_client_move_resize(p);

            return p->height;
          }
        else if (p->flags & CLIENT_TB_ALT_TRANS_FOR_DIALOG)
          {
            dbg("%s() IM trans for dialog found resizing..\n", __func__);

            toolbar_client_configure(p);
            toolbar_client_move_resize(p);
            return 0;
          }
      }
    }

  return 0;

#else
  Wm     *w = c->wm;
  Client *p  = NULL;
  int     south_panel_size = 0, south_total_size = 0;

  if (main_client_showing 
      && (c->flags & CLIENT_TOOLBARS_MOVED_FOR_FULLSCREEN))
    return 0;

  if (!main_client_showing 
      && !(c->flags & CLIENT_TOOLBARS_MOVED_FOR_FULLSCREEN))
    return 0;

  south_panel_size = wm_get_offsets_size(w, SOUTH, NULL, False); 
  south_total_size = wm_get_offsets_size(w, SOUTH, NULL, True); 

  c->flags ^= CLIENT_TOOLBARS_MOVED_FOR_FULLSCREEN;    

  if (south_total_size > south_panel_size) /* there are toolbars */
    {
      stack_enumerate(w, p)
      {
        /* move toolbar wins up/down over panels */
        if (p->type == MBCLIENT_TYPE_TOOLBAR && p->mapped) 
          {
            if (main_client_showing)
            {
              p->y += south_panel_size; 

              /* cover vertical panels */
              p->x = toolbar_win_offset(p);
              p->width = w->dpy_width - toolbar_win_offset(p);
            }
            else
            {
              /* uncover any vertical panels */
              p->x = toolbar_win_offset(p) 
                + wm_get_offsets_size(w, WEST,  NULL, False);
              p->width = w->dpy_width - toolbar_win_offset(p)
                - wm_get_offsets_size(w, WEST,  NULL, False)
                - wm_get_offsets_size(w, EAST,  NULL, False);


              p->y -= south_panel_size; 

            }

            p->move_resize(p);
            XMapRaised(w->dpy, p->frame);
          }
        else if (p->type == MBCLIENT_TYPE_PANEL && main_client_showing)
          {
            XLowerWindow(w->dpy, p->frame);
          }
      }

      return (south_total_size - south_panel_size);
    }

  return 0;
#endif
}

void
main_client_configure(Client *c)
{
  Wm *w = c->wm;
  int frm_size = main_client_title_height(c);
  int offset_south = theme_frame_defined_height_get(c->wm->mbtheme, 
                                        FRAME_MAIN_SOUTH);
  int offset_east  = theme_frame_defined_width_get(c->wm->mbtheme, 
                                       FRAME_MAIN_EAST );
  int offset_west  = theme_frame_defined_width_get(c->wm->mbtheme, 
                                       FRAME_MAIN_WEST );

  int h = wm_get_offsets_size(w, SOUTH, NULL, True);

  if (c->flags & CLIENT_TITLE_HIDDEN_FLAG) /* Decorations */
    frm_size = offset_south = offset_east = offset_west = 0;

   if ( c->flags & CLIENT_FULLSCREEN_FLAG )
     { 
       c->y = 0;  
       c->x = 0;
       c->width  = w->dpy_width;
       c->height = w->dpy_height - main_client_manage_toolbars_for_fullscreen(c, True);
     }
   else
     {
       c->y = wm_get_offsets_size(c->wm, NORTH, NULL, False) + frm_size;
       c->x = wm_get_offsets_size(c->wm, WEST,  NULL, False) + offset_west;
       c->width  = c->wm->dpy_width - ( offset_east + offset_west ) 
       - wm_get_offsets_size(c->wm, EAST,  NULL, False)
       - wm_get_offsets_size(c->wm, WEST,  NULL, False);

#ifdef USE_ALT_INPUT_WIN
       c->height = c->wm->dpy_height - c->y - h - offset_south - main_client_manage_toolbars_for_fullscreen(c, False);
#else
       c->height = c->wm->dpy_height - c->y - h - offset_south;
       main_client_manage_toolbars_for_fullscreen(c, False);
#endif
     }

   dbg("%s() configured as %i*%i+%i+%i, frame size is %i\n", 
       __func__, c->width, c->height, c->x, c->y, frm_size);

}

int
main_client_title_height(Client *c)
{
  if (c == NULL || c->type != MBCLIENT_TYPE_APP)
    return 0;

  if ( (!c->wm->config->use_title)
       || c->flags & CLIENT_FULLSCREEN_FLAG
       || c->flags & CLIENT_TITLE_HIDDEN_FLAG) 
    return 0;

  if ((c->wm->flags & TITLE_HIDDEN_FLAG) && c->type == MBCLIENT_TYPE_APP)
    return TITLE_HIDDEN_SZ;

  return theme_frame_defined_height_get(c->wm->mbtheme, FRAME_MAIN);
}

void
main_client_get_coverage(Client *c, int *x, int *y, int *w, int *h)
{
  int offset_south = theme_frame_defined_height_get(c->wm->mbtheme, 
                                        FRAME_MAIN_SOUTH);
  int offset_east  = theme_frame_defined_width_get(c->wm->mbtheme, 
                                       FRAME_MAIN_EAST );
  int offset_west  = theme_frame_defined_width_get(c->wm->mbtheme, 
                                       FRAME_MAIN_WEST );

  if (c->flags & CLIENT_TITLE_HIDDEN_FLAG)
    offset_south = offset_east = offset_west = 0; 

   *x = c->x - offset_west; 
   *y = c->y - main_client_title_height(c);
   *w = c->width + offset_east + offset_west;
   *h = c->height + main_client_title_height(c) + offset_south;

   dbg("%s() +%i+%i, %ix%i\n", __func__, *x, *y, *w, *h);
}

void
main_client_reparent(Client *c)
{
  Wm *w = c->wm;
  XSetWindowAttributes attr;
  int   frame_north_height;

  int offset_north = main_client_title_height(c);
  int offset_south = theme_frame_defined_height_get(w->mbtheme, 
                                        FRAME_MAIN_SOUTH);
  int offset_east  = theme_frame_defined_width_get(w->mbtheme, 
                                       FRAME_MAIN_EAST );
  int offset_west  = theme_frame_defined_width_get(w->mbtheme, 
                                         FRAME_MAIN_WEST );
  attr.override_redirect = True;
  attr.background_pixel  = w->grey_col.pixel; /* BlackPixel(w->dpy, w->screen); */
  attr.event_mask         = ChildMask|ButtonMask|ExposureMask;

  if (c->flags & CLIENT_TITLE_HIDDEN_FLAG)
    offset_south = offset_east = offset_west = 0; 

  c->frame =
    XCreateWindow(w->dpy, w->root, 
              c->x - offset_west, 
              c->y - offset_north,
              c->width + offset_east + offset_west, 
              c->height + offset_north + offset_south, 
              0,
              CopyFromParent, CopyFromParent, CopyFromParent,
              CWOverrideRedirect|CWEventMask|CWBackPixel,
              &attr);

  dbg("%s frame created : %i*%i+%i+%i\n",
      __func__, c->width, c->height + offset_north, c->x, c->y);

  frame_north_height = offset_north;

  if (!c->wm->config->use_title && c->flags & CLIENT_FULLSCREEN_FLAG) 
  {
    /* make sure the top frame is not 0 pixels high if fullscreen
     * else toggling will break. 
    */
    frame_north_height = theme_frame_defined_height_get(c->wm->mbtheme, 
                                          FRAME_MAIN);
  }

  if (!(c->flags & CLIENT_TITLE_HIDDEN_FLAG))
    client_decor_frames_init(c, 
                       offset_west, 
                       offset_east, 
                       ( c->flags & CLIENT_FULLSCREEN_FLAG) ?
                       : offset_north, 
                       offset_south);

  XClearWindow(w->dpy, c->frame);

  XSetWindowBorderWidth(w->dpy, c->window, 0);
  XAddToSaveSet(w->dpy, c->window); 
  XSelectInput(w->dpy, c->window, ColormapChangeMask|PropertyChangeMask);
  XReparentWindow(w->dpy, c->window, c->frame, offset_west, offset_north);
}


void
main_client_move_resize(Client *c)
{
  Wm *w = c->wm;

  int offset_south = theme_frame_defined_height_get(w->mbtheme, 
                                        FRAME_MAIN_SOUTH);
  int offset_east  = theme_frame_defined_width_get(w->mbtheme, 
                                       FRAME_MAIN_EAST );
  int offset_west  = theme_frame_defined_width_get(w->mbtheme, 
                                       FRAME_MAIN_WEST );

  if (c->flags & CLIENT_TITLE_HIDDEN_FLAG)
    offset_south = offset_east = offset_west = 0; 

  base_client_move_resize(c);

  XMoveResizeWindow(w->dpy, c->window, 
                offset_west, main_client_title_height(c), 
                c->width, c->height);

  XMoveResizeWindow(w->dpy, c->frame, 
                c->x - offset_west,
                c->y - main_client_title_height(c), 
                c->width + ( offset_east + offset_west),
                c->height + main_client_title_height(c) + offset_south);

  client_decor_frames_move_resize(c, 
                          offset_west, offset_east, 
                          main_client_title_height(c), offset_south);


/*
 * Disabled _NET_WM_SYNC code ( Alternate to above XMove*'s )
 * Is unfinished and initial testing did not seem to improve things.
 * Maybe re-try again at a later date.
 *
 * if (!c->ewmh_sync_is_waiting)
 *  {
 *    XMoveResizeWindow(w->dpy, c->window, 
 *                offset_west, main_client_title_height(c), 
 *                c->width, c->height);
 *   }
 * 
 * if (ewmh_sync_client_move_resize(c))
 *   {
 *     dbg("%s() not resizing frame yet\n", __func__);
 *     return; 
 *   }
 *
 * XMoveWindow(w->dpy, c->window, offset_west, main_client_title_height(c));
 * 
 * XResizeWindow(w->dpy, c->title_frame, 
 *          c->width + (offset_east + offset_west),
 *          c->height + main_client_title_height(c) + offset_south);
 * 
 * XMoveResizeWindow(w->dpy, c->frame, 
 *              c->x - offset_west,
 *              c->y - main_client_title_height(c), 
 *              c->width + ( offset_east + offset_west),
 *              c->height + main_client_title_height(c) + offset_south);
 *
 *  dbg("%s() resizing frame\n", __func__);
 *
 * c->ewmh_sync_is_waiting = False;
 */

}


void
main_client_toggle_fullscreen(Client *c)
{
  c->flags ^= CLIENT_FULLSCREEN_FLAG;

  ewmh_state_set(c); /* Let win know it fullscreen state has changed, it
                    could be waiting on this to adjust ui */

  main_client_configure(c);
  main_client_move_resize(c);

  if (!(c->flags & CLIENT_FULLSCREEN_FLAG))
    {
      /* Client was fullscreen - to be safe we redraw decoration buttons */
      client_buttons_delete_all(c);    
      c->redraw(c, False);
    }

  wm_activate_client(c); /* Reactivate, stacking order slightly different  */

  /* No need to ping here anymore
   * if (c->wm->config->ping_aggressive)
   *   ewmh_ping_client_start (c);
   */ 
}


/* redraws the frame */
void
main_client_redraw(Client *c, Bool use_cache)
{
  Wm  *w = c->wm;
  Bool is_shaped = False;
  int  width = 0, height = 0;
  int  offset_south, offset_east, offset_west;

  dbg("%s() called on %s\n", __func__, c->name);

   if (!w->config->use_title || c->flags & CLIENT_TITLE_HIDDEN_FLAG)
     return;
   
   if (w->flags & TITLE_HIDDEN_FLAG)
   {
     XUnmapWindow(w->dpy, client_title_frame(c));
     return;
   }

   if (use_cache && c->have_set_bg)  return ;

   offset_south = theme_frame_defined_height_get(w->mbtheme, 
                                     FRAME_MAIN_SOUTH);
   offset_east  = theme_frame_defined_width_get(w->mbtheme, 
                                    FRAME_MAIN_EAST );
   offset_west  = theme_frame_defined_width_get(w->mbtheme, 
                                    FRAME_MAIN_WEST );
 
   width = c->width + offset_east + offset_west;
   height = theme_frame_defined_height_get(w->mbtheme, FRAME_MAIN);
   
   is_shaped = theme_frame_wants_shaped_window( w->mbtheme, FRAME_MAIN);

   dbg("%s() cache failed, actual redraw on %s\n", __func__, c->name);

   if (is_shaped) 
     client_init_backing_mask(c, c->width + offset_east + offset_west, 
                        c->height, height , offset_south,
                        width - offset_east, offset_west);

   dbg("%s() calling theme_frame_paint()\n", __func__); 

   theme_frame_paint(w->mbtheme, c, FRAME_MAIN, width, height); 

   theme_frame_paint(w->mbtheme, c, FRAME_MAIN_WEST, offset_west, c->height); 
  
   theme_frame_paint(w->mbtheme, c, FRAME_MAIN_EAST, offset_east, c->height); 

   theme_frame_paint(w->mbtheme, c, FRAME_MAIN_SOUTH, 
                 c->width + offset_east + offset_west, offset_south); 

   if (!(c->flags & CLIENT_IS_DESKTOP_FLAG))
     theme_frame_button_paint(w->mbtheme, c, BUTTON_ACTION_CLOSE, 
                        INACTIVE, FRAME_MAIN, width, height);

   theme_frame_button_paint(w->mbtheme, c, BUTTON_ACTION_HIDE, 
                      INACTIVE, FRAME_MAIN, width, height);

   theme_frame_button_paint(w->mbtheme, c, BUTTON_ACTION_MIN, 
                      INACTIVE, FRAME_MAIN, width, height);

   if (!(w->flags & SINGLE_FLAG))
   {
      dbg("%s() painting next / prev buttons\n", __func__);
      theme_frame_button_paint(w->mbtheme, c, BUTTON_ACTION_MENU, 
                         INACTIVE, FRAME_MAIN, width, height);
      theme_frame_button_paint(w->mbtheme, c, BUTTON_ACTION_NEXT, 
                         INACTIVE, FRAME_MAIN, width, height);
      theme_frame_button_paint(w->mbtheme, c, BUTTON_ACTION_PREV, 
                         INACTIVE, FRAME_MAIN, width, height);
   } else {
     client_button_remove(c, BUTTON_ACTION_NEXT);
     client_button_remove(c, BUTTON_ACTION_PREV);

     if (!(w->flags & DESKTOP_DECOR_FLAG)
         && wm_get_desktop(c->wm)) /* Paint the dropdown for the desktop */
       {
       dbg("%s() have desktop\n", __func__);
       theme_frame_button_paint(w->mbtheme, c, BUTTON_ACTION_MENU, 
                          INACTIVE, FRAME_MAIN, width, height);

       theme_frame_button_paint(w->mbtheme, c, BUTTON_ACTION_DESKTOP, 
                          INACTIVE, FRAME_MAIN, width, height);
       }
     else 
       {
       dbg("%s() removing menu button\n", __func__ );
       client_button_remove(c, BUTTON_ACTION_MENU);
       }
   }

   if (c->flags & CLIENT_ACCEPT_BUTTON_FLAG)
      theme_frame_button_paint(w->mbtheme, c, BUTTON_ACTION_ACCEPT, 
                         INACTIVE, FRAME_MAIN, width, height);

   if (c->flags & CLIENT_HELP_BUTTON_FLAG)
     {
       dbg("%s() painting help button\n", __func__);
       theme_frame_button_paint(w->mbtheme, c, BUTTON_ACTION_HELP, 
                        INACTIVE, FRAME_MAIN, width, height);
     }

   if (c->flags & CLIENT_CUSTOM_BUTTON_FLAG)
     {
       dbg("%s() painting help button\n", __func__);
       theme_frame_button_paint(w->mbtheme, c, BUTTON_ACTION_CUSTOM, 
                        INACTIVE, FRAME_MAIN, width, height);
     }


  if (is_shaped)   /* XXX do we really need titleframe here ? */
    {
      XRectangle rects[1];

      rects[0].x = 0;
      rects[0].y = height;
      rects[0].width = width;
      rects[0].height = c->height;

      XShapeCombineRectangles ( w->dpy, c->frame, 
                        ShapeBounding,
                        0, 0, rects, 1, ShapeSet, 0 );

      XShapeCombineMask( c->wm->dpy, c->frames_decor[NORTH], 
                   ShapeBounding, 0, 0, 
                   c->backing_masks[MSK_NORTH], ShapeSet);

      XShapeCombineMask( c->wm->dpy, c->frames_decor[SOUTH], 
                   ShapeBounding, 0, 0,
                   c->backing_masks[MSK_SOUTH], ShapeSet);


      XShapeCombineShape ( c->wm->dpy, 
                     c->frame,
                     ShapeBounding, 0, 0, 
                     c->frames_decor[NORTH],
                     ShapeBounding, ShapeUnion);

      XShapeCombineShape ( c->wm->dpy, 
                     c->frame,
                     ShapeBounding, 0, c->height + height, 
                     c->frames_decor[SOUTH],
                     ShapeBounding, ShapeUnion);
    }

#if 0

#ifdef STANDALONE
   XSetWindowBackgroundPixmap(w->dpy, c->title_frame, c->backing);
#else
   XSetWindowBackgroundPixmap(w->dpy, c->title_frame, 
                        mb_drawable_pixmap(c->backing));
#endif

   XClearWindow(w->dpy, c->title_frame);

#ifdef STANDALONE
   XFreePixmap(w->dpy, c->backing);
   c->backing = None;
#else
   mb_drawable_unref(c->backing);
   c->backing = NULL;
#endif

#endif /* if 0 */

   c->have_set_bg = True;
}


void main_client_button_press(Client *c, XButtonEvent *e)
{
  Wm *w = c->wm;

  int     ch = 0, offset_east = 0, offset_west = 0, total_w = 0;
  Client *p  = NULL;

   if (!w->config->use_title) return;

   if (w->flags & TITLE_HIDDEN_FLAG)
   {
      main_client_toggle_title_bar(c);
      /* XXX What is this doing ?
      XMapWindow(w->dpy, c->title_frame);
      XMapSubwindows(w->dpy, c->title_frame);
      */
      return;
   }

   if (w->config->super_modal)
     {
       stack_enumerate(w, p)
       {
         if (p->trans == c && (p->flags & CLIENT_IS_MODAL_FLAG))
           {
             MBList *button_item = client_get_button_list_item_from_event(c, e);
             /* In the precense of a modal transient dialog ignore 
            * certain buttons. 
            *
            */
             if ((button_item && button_item->id == BUTTON_ACTION_CUSTOM)
               || (button_item && button_item->id == BUTTON_ACTION_MIN)
               || (button_item && button_item->id == BUTTON_ACTION_CLOSE))
             {
               if (button_item->id == BUTTON_ACTION_CLOSE)
                 {
                   /* initiate pinging the app anyway for close button */
                   if (c->has_ping_protocol && c->pings_pending == -1) 
                   {
                     c->pings_pending = 0;
                     w->n_active_ping_clients++;
                   }
                 }
               return;
             }
           }
       }
     }

   offset_east  = theme_frame_defined_width_get(w->mbtheme, 
                                    FRAME_MAIN_EAST );
   offset_west  = theme_frame_defined_width_get(w->mbtheme, 
                                    FRAME_MAIN_WEST );


   ch = theme_frame_defined_height_get(w->mbtheme, FRAME_MAIN);

   total_w = c->width + offset_east + offset_west;

   switch (client_button_do_ops(c, e, FRAME_MAIN, total_w, ch))
     {
      case BUTTON_ACTION_DESKTOP:
       wm_toggle_desktop(w);
       break;
      case BUTTON_ACTION_CLOSE:
       client_deliver_delete(c);
       break;
      case BUTTON_ACTION_NEXT:
      wm_activate_client(stack_cycle_backward(w, MBCLIENT_TYPE_APP));
       break;
      case BUTTON_ACTION_PREV:
      wm_activate_client(stack_cycle_forward(w, MBCLIENT_TYPE_APP));
       break;
      case BUTTON_ACTION_MENU:
       select_client_new(w);
       break;
      case BUTTON_ACTION_HIDE:
       main_client_toggle_title_bar(c);
       break;
      case BUTTON_ACTION_MIN:
       main_client_iconize(c);
       break;
      case BUTTON_ACTION_HELP:
      client_deliver_wm_protocol(c, w->atoms[_NET_WM_CONTEXT_HELP]);
       break;
      case BUTTON_ACTION_ACCEPT:
      client_deliver_wm_protocol(c, w->atoms[_NET_WM_CONTEXT_ACCEPT]);
       break;
      case BUTTON_ACTION_CUSTOM:
      client_deliver_wm_protocol(c, w->atoms[_NET_WM_CONTEXT_CUSTOM]);
       break;
      case -1:           
      /* Cancelled  */
       break;
      case 0:
       /* Not on button */
       break;
   }
}

void
main_client_toggle_title_bar(Client *c)
{
  Wm *w = c->wm;

  Client *p = NULL;
  int prev_height = main_client_title_height(c);
  int y_offset = wm_get_offsets_size(c->wm, NORTH, NULL, False);

  if (c->flags & CLIENT_TITLE_HIDDEN_FLAG)
    return;
  
  w->flags ^= TITLE_HIDDEN_FLAG;
  
  dbg("%s() called\n", __func__);
  
  XGrabServer(w->dpy);
  
  theme_img_cache_clear( w->mbtheme,  FRAME_MAIN );
  
  stack_enumerate(c->wm, p)
    if (p->type == MBCLIENT_TYPE_APP)
      {
      if (w->flags & TITLE_HIDDEN_FLAG)
        {  /* hide */
          p->height += (prev_height - TITLE_HIDDEN_SZ );
          p->y = y_offset + TITLE_HIDDEN_SZ;
          
          if (w->have_titlebar_panel 
            && mbtheme_has_titlebar_panel(w->mbtheme))
            {
            w->have_titlebar_panel->ignore_unmap++;
            XUnmapWindow(w->dpy, w->have_titlebar_panel->frame);
            }
          
        } else {
          /* show */
          p->y = main_client_title_height(p) + y_offset;
          p->height -= ( main_client_title_height(p) - TITLE_HIDDEN_SZ );
          XMapWindow(w->dpy, client_title_frame(p)); /* prev will have unmapped */
          
          if (w->have_titlebar_panel
            && mbtheme_has_titlebar_panel(w->mbtheme))
            XMapRaised(w->dpy, w->have_titlebar_panel->frame);
          
        }
      p->move_resize(p);
      p->redraw(p, False);
      }
  
  XUngrabServer(w->dpy);
}

/* This is called when a main client is not visible anymore - 
   i.e. another one is activated */
void
main_client_hide(Client *c)
{
  Wm *w = c->wm;

  /* If we dont have focus atm, and one of our dialogs likely does,
     then remember it for next time we come active
  */
  if (w->focused_client != c 
      && w->focused_client       
      && w->focused_client->type == MBCLIENT_TYPE_DIALOG
      && w->focused_client->trans != NULL)
    {
      c->next_focused_client = w->focused_client;
    }
  else 
    {
      c->next_focused_client = NULL;

      /* If were focused, unset focus for something better to be found */
      if (w->focused_client == c)
      w->focused_client = NULL;
    }
}

void
main_client_iconize(Client *c)
{
  Wm *w = c->wm;
  Client *p = NULL;

  dbg("%s() called on %s\n", __func__, c->name);

  client_set_state(c, IconicState);
  c->flags |= CLIENT_IS_MINIMIZED;

  /* Make sure any transients get iconized too */
  stack_enumerate(w, p)
    if (p->trans == c)
      p->iconize(p);

  main_client_unmap(c);
}

void
main_client_show(Client *c)
{
  Wm     *w = c->wm;

  Client *visible_app_client = NULL;

  dbg("%s() called on %s\n", __func__, c->name);
   
  if (c->flags & CLIENT_NO_FOCUS_ON_MAP)
    visible_app_client = wm_get_visible_main_client(w);

   if (w->flags & DESKTOP_RAISED_FLAG) 
     {
       c->flags |= CLIENT_NEW_FOR_DESKTOP;
     }
   else
     {
       /* Only reset this flag if were not the main client. 
        * - ie we've paged to another app and come back. 
        * Avoid problem of open app *and* the dialog from desktop, close 
        * app then does not go back to desktop. 
       */
       if (wm_get_visible_main_client(w) != c)
       c->flags &= ~CLIENT_NEW_FOR_DESKTOP;
     }

   /* Move this client and any transients to the very top of the stack.
      wm_activate_client() ( call it sync_display ? ) will then take
      care of painels etc as it can use active client as a 'watermark' 
   */
   stack_move_top(c);

   stack_dump(w);

   if (!c->mapped)
     {
       if (c->flags & CLIENT_IS_MINIMIZED)
       {
         Client *p = NULL;

         /* Reset state from Iconized */
         client_set_state(c, NormalState);
         c->flags &= ~CLIENT_IS_MINIMIZED;

         /* Make sure any dialogs are shown too */
         stack_enumerate(w, p)
           if (p->trans == c)
             {
             p->show(p);
             /* To handle delay mapping.. */
             XMapSubwindows(w->dpy, p->frame);
             XMapWindow(w->dpy, p->frame);
             }
       }

       if (c->flags & CLIENT_NO_FOCUS_ON_MAP)
       {
         if (visible_app_client)
           {
             stack_move_above_client (c, visible_app_client->below);
             c->flags |= CLIENT_DELAY_MAPPING;
           }
         c->flags &= ~CLIENT_NO_FOCUS_ON_MAP;
       }

       if (!(c->flags & CLIENT_DELAY_MAPPING))
       {
         XMapSubwindows(w->dpy, c->frame);
         XMapWindow(w->dpy, c->frame);
       }
     }

   c->mapped = True;
}

void
main_client_unmap(Client *c)
{
   Wm     *w = c->wm;
   Client *next_client = NULL; 

   dbg("%s called for %s\n", __func__, c->name);

   if ( c->flags & CLIENT_FULLSCREEN_FLAG )
     main_client_manage_toolbars_for_fullscreen(c, False);

   /* Are we at the top of the stack ? */
   if (c == w->stack_top_app)
     {
       next_client = stack_get_below(c, MBCLIENT_TYPE_APP);
       
       dbg("%s() at stack top\n", __func__ );

       /* Is this the only main client left? */
       if(next_client == c) 
       {
         dbg("%s() only client left\n", __func__ );

         if (w->flags & SINGLE_FLAG)
           w->flags ^= SINGLE_FLAG; /* single flag off ( for menu button ) */
         
         /* is there a desktop ? */
         next_client = wm_get_desktop(w);
       }
       else
       {
         /* There are more main clients left, but we may have been 
            * opened from the desktop and it therefor makes sense to
            * go back there. 
          */
         if (c->flags & CLIENT_NEW_FOR_DESKTOP)
           {
             /* Make sure we set stack_top_app so desktop 
                * toggling still works.
                */
             w->stack_top_app = next_client; 
             next_client = wm_get_desktop(w);
           }
       }

       /* if we havn't set stack_top_app to something else let 
      * wm_activate_client(next_client) below update this */
       if (c == w->stack_top_app)
       w->stack_top_app = NULL;
     }

   c->mapped = False;

   if (next_client /* only 1 main_client left ? */
       && next_client->type == MBCLIENT_TYPE_APP
       && (next_client == stack_get_below(next_client, MBCLIENT_TYPE_APP)))
     {
       dbg("%s() turning on single flag\n", __func__);
       w->flags |= SINGLE_FLAG; /* turn on single flag for menu button */
       main_client_redraw(next_client, False);
     }

   XUnmapWindow(w->dpy, c->frame); 

   if (c == w->focused_client)
     w->focused_client = NULL;

   if (next_client)
     wm_activate_client(next_client);   
}

void
main_client_destroy(Client *c)
{
   dbg("%s called for %s\n", __func__, c->name);
  
   main_client_unmap(c);

   base_client_destroy(c); 
}





Generated by  Doxygen 1.6.0   Back to index