marco之窗口最大化流程分析

环境:debian 12.5、mate desktop。
参考:marco 1.20.2

 如上图,当点击窗口菜单的最大化按钮,marco 如何与系统交互来响应此要求呢?
首先,meta_window_maximize 函数负责将窗口最大化的具体操作。此函数会在menu_callback中被调用。menu_callback会作为参数传递给函数meta_ui_window_menu_new.

因此,需要跟踪函数meta_ui_window_menu_new流程,确定menu_callback存放的位置。

void meta_window_show_menu (MetaWindow *window,
                       int         root_x,
                       int         root_y,
                       int         button,
                       guint32     timestamp)
{
  ......
menu =
    meta_ui_window_menu_new (window->screen->ui,
                             window->xwindow,
                             ops,
                             insensitive,
                             meta_window_get_net_wm_desktop (window),
                             meta_screen_get_n_workspaces (window->screen),
                             menu_callback,
                             NULL);
  ......
}

MetaWindowMenu*
meta_ui_window_menu_new  (MetaUI             *ui,
                          Window              client_xwindow,
                          MetaMenuOp          ops,
                          MetaMenuOp          insensitive,
                          unsigned long       active_workspace,
                          int                 n_workspaces,
                          MetaWindowMenuFunc  func,
                          gpointer            data)
{
  return meta_window_menu_new (ui->frames,
                               ops, insensitive,
                               client_xwindow,
                               active_workspace,
                               n_workspaces,
                               func, data);
}

MetaWindowMenu*
meta_window_menu_new   (MetaFrames         *frames,
                        MetaMenuOp          ops,
                        MetaMenuOp          insensitive,
                        Window              client_xwindow,
                        unsigned long       active_workspace,
                        int                 n_workspaces,
                        MetaWindowMenuFunc  func,
                        gpointer            data)
{
  ......
MetaWindowMenu *menu;
......
menu->func = func;
......
else if (menuitem.type != MENU_ITEM_SEPARATOR)
{
              ......
              md = g_new (MenuData, 1);

              md->menu = menu;
             ......

              g_signal_connect_data (G_OBJECT (mi),
                                     "activate",
                                     G_CALLBACK (activate_cb),
                                     md,
                                     (GClosureNotify) g_free, 0);
 }

}


}

根据上述代码流程,menu_callback函数存放在MenuData数据结构中menu成员的func指针中。
最终,menu_callback会在active_cb函数中被调用。 

static void activate_cb(GtkWidget* menuitem, gpointer data)
{
  ......
  md = data;
  ......
(*md->menu->func)(
        md->menu,
        GDK_DISPLAY_XDISPLAY (gdk_display_get_default()),
        md->menu->client_xwindow,
        gtk_get_current_event_time(),
        md->op,
        GPOINTER_TO_INT(g_object_get_data(G_OBJECT(menuitem), "workspace")),
        md->menu->data);
}

 那么函数meta_ui_window_menu_new又是怎么被调用的呢?

void
meta_window_show_menu (MetaWindow *window,
                       int         root_x,
                       int         root_y,
                       int         button,
                       guint32     timestamp)
{
    ......
    menu =
    meta_ui_window_menu_new (window->screen->ui,
                             window->xwindow,
                             ops,
                             insensitive,
                             meta_window_get_net_wm_desktop (window),
                             meta_screen_get_n_workspaces (window->screen),
                             menu_callback,
                             NULL);

}

void
meta_core_show_window_menu (Display *xdisplay,
                            Window   frame_xwindow,
                            int      root_x,
                            int      root_y,
                            int      button,
                            guint32  timestamp)
{
  MetaWindow *window = get_window (xdisplay, frame_xwindow);

  if (meta_prefs_get_raise_on_click ())
    meta_window_raise (window);
  meta_window_focus (window, timestamp);

  meta_window_show_menu (window, root_x, root_y, button, timestamp);
}

static gboolean
meta_frames_button_press_event (GtkWidget      *widget,
                                GdkEventButton *event)
{
  ......
  MetaFrameControl control;
  ......
  control = get_control (frames, frame, event->x, event->y);
  ......
    if ((event->button == 1 &&
      (control == META_FRAME_CONTROL_MINIMIZE ||
       control == META_FRAME_CONTROL_DELETE ||
       control == META_FRAME_CONTROL_SHADE ||
       control == META_FRAME_CONTROL_UNSHADE ||
       control == META_FRAME_CONTROL_ABOVE ||
       control == META_FRAME_CONTROL_UNABOVE ||
       control == META_FRAME_CONTROL_STICK ||
       control == META_FRAME_CONTROL_UNSTICK ||
       control == META_FRAME_CONTROL_MENU)) ||
      (control == META_FRAME_CONTROL_MAXIMIZE ||
       control == META_FRAME_CONTROL_UNMAXIMIZE))
    {
      ......
      if (op == META_GRAB_OP_CLICKING_MENU)
        {
            ......
           if (op == META_GRAB_OP_CLICKING_MENU)
          {
                        meta_core_show_window_menu (GDK_DISPLAY_XDISPLAY (gdk_display_get_default ()),
                                      frame->xwindow,
                                      rect->x + dx,
                                      rect->y + rect->height + dy,
                                      event->button,
                                      event->time);
          }
        }
    }
  ......
}

static void
meta_frames_class_init (MetaFramesClass *class)
{
  ......
GtkWidgetClass *widget_class;
......
widget_class = (GtkWidgetClass*) class;
......
widget_class->button_press_event = meta_frames_button_press_event;
......

}

最终,函数的调用源头是在meta_frame这个新创建的GObject的button_press_event中。 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值