Skip to content

Latest commit

 

History

History
208 lines (163 loc) · 9.61 KB

gnome-shell-panel.org

File metadata and controls

208 lines (163 loc) · 9.61 KB

gnome-shell 分析

1 Panel的组成

panel上有三个组成部分:

  • _leftBox: 放两个组件: ActivitiesButton, AppButton
  • _centerBox: 放一个组件: dateMenu
  • _rightBox: 存放系统indicator

1.1 _leftBox

this._leftBox = new St.BoxLayout({ name: 'panelLeft' });
if (global.session_type == Shell.SessionType.USER) {
    this._activitiesButton = new ActivitiesButton();
    this._activities = this._activitiesButton.actor;
    this._leftBox.add(this._activities);

    // The activities button has a pretend menu, so as to integrate
    // more cleanly with the rest of the panel
    this._menus.addMenu(this._activitiesButton.menu);

    this._appMenu = new AppMenuButton(this._menus);
    this._leftBox.add(this._appMenu.actor);
}

上面代码给出了_leftBox的创建及添加ActivitiesButton和appMenu的过程。

1.1.1 ActivitiesButton

定义在 panel.js 中。 label和hotcorner通过下面语句实现。

this._label = new St.Label({ text: _("Activities") });
container.add_actor(this._label);

this.actor.label_actor = this._label;

this._hotCorner = new Layout.HotCorner();
container.add_actor(this._hotCorner.actor);

activitiesButton的press/release事件需要重新定义,因为其实现的功能不同于一般的menuButton.所以通过以下语句实现:

this.menu.open = Lang.bind(this, this._onMenuOpenRequest);
this.menu.close = Lang.bind(this, this._onMenuCloseRequest);
this.menu.toggle = Lang.bind(this, this._onMenuToggleRequest);

button click/key press事件通过以下语句定义:

this.actor.connect_after('button-release-event', Lang.bind(this, this._onButtonRelease));
this.actor.connect_after('key-release-event', Lang.bind(this, this._onKeyRelease));

回调函数中调用 Main.overview.toggle(); 用来触发overview。

1.1.2 AppMenuButton

定义在 panel.js 文件中。作用是跟踪当前应用程序。同时提供launchApp时的notification。注意在overview状态时是不显示此button的,所以在代码中可以看到这两行:

Main.overview.connect('hiding', Lang.bind(this, function () {
    this.show();
}));
Main.overview.connect('showing', Lang.bind(this, function () {
    this.hide();
}));

1.2 _centerBox

_centerBox的创建

this._centerBox = new St.BoxLayout({ name: 'panelCenter' });
this.actor.add_actor(this._centerBox);

_centerBox button的添加

this._centerBox.add(this._dateMenu.actor, { y_fill: true });
this._menus.addMenu(this._dateMenu.menu);

1.3 _rightBox

_rightBox的创建

_rightBox indicator的添加: 首先在 panel.js 文件首部定义了一些系统indicator常量,如下所示:

const STANDARD_STATUS_AREA_ORDER = ['a11y', 'keyboard', 'volume', 'bluetooth', 'network', 'battery', 'userMenu'];
const STANDARD_STATUS_AREA_SHELL_IMPLEMENTATION = {
    'a11y': imports.ui.status.accessibility.ATIndicator,
    'volume': imports.ui.status.volume.Indicator,
    'battery': imports.ui.status.power.Indicator,
    'keyboard': imports.ui.status.keyboard.XKBIndicator,
    'userMenu': imports.ui.userMenu.UserMenuButton
};

其后,在function : startStatusArea 中用for循环将这些indicator添加到_rightBox中,所以具体的函数调用如下图所示:

./include/images/panelIndicationInsert.png

添加流程大致如此,startStatusArea会在main.js中被下面这条语句执行。

panel.startStatusArea();

2 panel menu button的实现

panelMenu.js 定义了panel menu button。其中先后定义了ButtonBox/Button/SystemStatusButton/三个对象,ButtonBox作为基类,Button继承ButtonBox,SystemStatusButton继承Button, panel.js 中_rightBox添加的indicator都属于SystemStatusButton。

panelMenu.js Button对象的定义中,引入了menu成员对象,如下代码所示:

if (dontCreateMenu)
    this.menu = null;
else
    this.setMenu(new PopupMenu.PopupMenu(this.actor, menuAlignment, St.Side.TOP, 0));

然后在button press事件的回调中执行如下语句:

_onButtonPress: function(actor, event) {
    if (!this.menu)
        return;

    this.menu.toggle();
},

popupMenu.js PopupMenuBase基类中toggle函数如下所示:

toggle: function() {
    if (this.isOpen)
        this.close(true);
    else
        this.open(true);
},

这样,调用open函数show出菜单,那么菜单是什么组件?答案是BoxPointer, 也就是说status indicator 点击打开的菜单控件和messageTray上通知icon点击打开的messageInfo是一个组件,可以通过 PopupMenu 对象的”constructor”中得到证明。代码如下:

this._boxPointer = new BoxPointer.BoxPointer(arrowSide,
                                             { x_fill: true,
                                               y_fill: true,
                                               x_align: St.Align.START });
this.actor = this._boxPointer.actor;

所以open函数的实现也就不难理解,关键代码如下:

this._boxPointer.setPosition(this.sourceActor, this._arrowAlignment);
this._boxPointer.show(animate);

各种 menuItem 定义也在在 popupMenu.js ,主要的类型如下表:

Namedescription
PopupBaseMenuItemMenuItem基类
PopupMenuItem类似一个label,创建此对象会在popupMenu中创建一个label,如volume indicator的第一行“Volume”就是一个PopupMenuItem
PopupSeparatorMenuItemmenuItem之间的分割空间,用于UI美化
PopupAlternatingMenuItemitem label可选择,有DEFAULT/ALTERNATIVE两块label可供选择
PopupSliderMenuItem离散划动控件,典型: 音量控制
Switch二进制开关控件的基类
PopupSwitchMenuItem二进制开关控件
PopupImageMenuItem
PopupMenuBase
PopupMenu
PopupSubMenu
PopupMenuSection
PopupSubMenuMenuItem
PopupComboMenu
PopupComboBoxMenuItem
RemoteMenu
PopupMenuManager

popupMenu.js/还定义了一个辅助function: /addSettingsAction 直接添加一个PopupMenuItem将之与对应app的desktop相关联。

对statusBar以及上面的控件的结构大致如此。