Metacity -- Gnome的默认窗口管理器

本文深入探讨了使用XML格式配置Metacity主题的过程,包括主题设计、配置文件结构、支持的窗口类型、样式、FrameGeometry、DrawingOperations等关键概念。通过实例展示了如何创建和应用主题,以及如何通过gconf-editor等工具查看和修改当前主题。

主题设计

Metacity 主题配置文件基于 XML 格式。

配置文件

创建文件和目录:

$PREFIX/share/themes/[theme_name]/metacity-1/
$HOME/.themes/[theme_name]/metacity-1/

比如 Moblin 的主题 Moblin-Netbook ,以后都以这个主题为例。

/usr/share/themes/Moblin-Netbook/metacity-1/metacity-theme-1.xml

基本概念

支持的 Window 类型

Metacity 有 6 中窗口类型:

  1. normal

    a normal top-level window

  2. dialog

    a dialog window

  3. modal_dialog

    a dialog window that has modal state ie. intervention required by user before they can interact with it's parent window

  4. menu

    a pinnable menu window ie. tearoff menu

  5. utility

    a small persistant utility window ie. paletde or toolbox

  6. border

    a window that should not show any decorations typically ie. full screen window

Styles

对于每种 Window 类型,都需要为之设置一个 "style set" (或者称 window decoration )。 一个 "style set" 是几中不同的 "frame states" 的组合 styles 。"frame states" 有以下几种声明:

  • window 是聚焦还是没聚焦 (focused or un-focused)
  • window 是 maximized or shaded [or both]
  • window 能否被 vertically, horizontally, vertically and horizontally resized

一个 "frame state" 对于一个 "frame style" (都没有s,指单个)。"frame style" 化分为两部分: frame 'pieces' 和 window 'buttons'。这样分开更容 易定制 Metacity 主题。

Frame pieces

Metacity 有以下几种 frame pieces :

entire_background the whole frame of the window which is drawn first
titlebar 程序窗口的上面(俗称:标题栏)
titlebar_middle 标题栏的中间,不包括任何 "edge"
left_titlebar_edge 标题栏左边边缘
right_titlebar_edge 标题栏右边边缘
top_titlebar_edge 标题栏顶部边缘
bottom_titlebar_edge 标题栏底部边缘
title 包含标题的部分
left_edge frame 的左边边缘
right_edge frame 的右边边缘
bottom_edge frame 的底部边缘
overlay same as entire_background, only that it is drawn last
Window Buttons

Metacity 有以下几种 Window Buttons :

close 关闭按钮
maximize 最大化按钮
minimize 最小化
menu 菜单按钮

Buttons 可以有下面几种位置:

left_left_background 左边第一个按钮的背景
left_middle_background 左边第二个按钮的背景
left_right_background 左边第三个按钮的背景
right_left_background 右边第一个按钮的背景
right_middle_background 右边第二个按钮的背景
right_right_background 右边第三个按钮的背景

对于窗口上的每个按钮,需要设置一个在给出一个 "button state" 时的怎么样 显示。 Metacity 的按钮状态有:

normal 常规显示
pressed 鼠标点击 (clicked) 后的显示
prelight 聚焦时候显示
Window menus

通常是在标题栏点击右键弹出 menu ,或者标题栏设置一个 menu icons,点击这 个 menu icons 弹出菜单。菜单的上通常有下列列表:

close 关闭
maximize 最大化
minimize 最小化
unmaximize 取消最大化

而且可以设置在下面几种情况下,对于的 GtkStateType :

normal menu icon 常规显示
prelight menu icon 列表中的项目被聚焦后怎样显示
active 激活后又怎么显示
selected 选择后又怎么显示
insensitive 灰色状态(此时不可用)如何显示

测试 Themes

当然可以直接安装主题测试了,不过这有点傻。可以使用 metacity-theme-viewer 工具查看一个主题的面貌。不带参数的时候,显示当前 主题,后接一个主题名字作为参数,可以显示这个主题的面貌,这样很方便。注 意:主题名字是 /usr/share/themes 下的目录名,或者其他地方。

应用主题

使用 gconftool-2 或者使用 GUI 程序可以应用一个主题。

gconftool-2 --type=string --set /apps/metacity/general/theme 主题名

再次提醒:主题通常放在 /usr/share/themes 下。

查看当前主题,可以使用 gconf-editor 工具,也可以使用 :

gconftool-2 --dump /apps/metacity/general

进一步细究

Frame Geometry

这是你第一个要设置的! 如下所示,name 字段是后面给出 "frame style" 时的 参考名字。

<frame_geometry name="my_frame_geometry">

   <!-- This is where we need to start specifying your frame geometry -->

</frame_geometry>

下面图片显示了在 frame_geometry 中可以设置的宽度或长度:

frame geometry 有一些可选的属性:

has_title 默认是 true ,确定 title text height 是否包括进 height 计算
title_scale 使用 Pango 标记 — xx-small, x-small, small, medium, large, x-large and xx-large 。缺省取决于桌面字体。
rounded_top_left Determines whether the top left corner of the window should be rounded. This defaults to false if not specified.
rounded_top_right Determines whether the top right corner of the window should be rounded. This defaults to false if not specified.
rounded_bottom_left Determines whether the bottom left corner of the window should be rounded. This defaults to false if not specified.
rounded_bottom_right Determines whether the bottom right corner of the window should be rounded. This defaults to false if not specified.

示例:

<frame_geometry name="normal" rounded_top_left="true" rounded_top_right="true" rounded_bottom_left="false" rounded_bottom_right="false">
  <distance name="left_width" value="2"/>
  <distance name="right_width" value="2"/>
  <distance name="bottom_height" value="2"/>
  <distance name="left_titlebar_edge" value="10"/>
  <distance name="right_titlebar_edge" value="1"/>
  <aspect_ratio name="button" value="1"/>
  <distance name="title_vertical_pad" value="2"/>
  <border name="title_border" left="0" right="6" top="6" bottom="6"/>
  <border name="button_border" left="6" right="6" top="6" bottom="6"/>
</frame_geometry>

frame geomtry 设置可以继承,设置 parent 字段:

<frame_geometry name="normal_maximized" parent="normal" rounded_top_left="false" rounded_top_right="false" rounded_bottom_left="false" rounded_bottom_right="false">
        <distance name="left_width" value="0"/>
        <distance name="right_width" value="0"/>
        <distance name="bottom_height" value="0"/>
        <distance name="left_titlebar_edge" value="10"/>
        <distance name="right_titlebar_edge" value="0"/>
</frame_geometry>

Instead of specifying button widths and heights, you can specify an aspect ratio instead.

<aspect_ratio name="button" value="1.0"/>
Drawing Operations

这个是 Metacity 主题设计的核心任务。要为 frame 设置一个 draw opt,需要 为 'frame piece' 匹配一个 drawing operation 。

<draw_ops name="focus_outline">
  <rectangle color="#202e31"
             x="0" y="0"
             width="width-1"
             height="height-1" />
  <rectangle color="#202e31"
             x="1" y="1"
             width="width-3"
             height="height-3" />
</draw_ops>
Operators

下面一些操作符可以用在 Drawing operations 里:

Operator Meaning Example
+ Plus 2 + 3
- Minus 5 - 4
星号 Multiply 3 * 2
/ Divide 10 / 2
% Modulus 34 % 3
`max` Maximum 4 `max` 5
`min` Minimum 7 `min` 3
() Parenthesis (5 * 3) + 5
Constants (常量)

在 drawing operations 过程中,可以使用以前定义的变量或常量。常量的定义 需要声明,并且名字首字母要大写:

<!-- button inside padding -->
<constant name="ButtonIPad" value="4"/>

下面是可以直接使用的预定义变量:

width Width of the target area
height Height of the target area
object_width Natural width of the object being drawn
object_height Natural height of the object being drawn
left_width Distance from left of frame to client window
right_width Distance from right of frame to client window
top_height Distance from top of frame to client window
bottom_height Distance from bottom of frame to client window
mini_icon_width Width of mini icon for window
mini_icon_height Height of mini icon for window
icon_width Width of large icon
icon_height Height of large icon
title_width Width of title text
title_height Height of title text
Operations

Metacity 支持下面几种操作:

line

通过给出 origin (x1,y1) 和 destination (x2,y2) 和 color ,画一条线。 color 可以是如 "blue" 一样的名字,也可以是如 "#FF0099" 一样的数值,或者 是 GTK theme 的形式:"gtk:base[NORMAL]"。

<draw_ops name="close_button_icon">
  <line color="#bbbbbb" width="2"
        x1="ButtonIPad" y1="ButtonIPad" x2="width-ButtonIPad-1" y2="height - ButtonIPad-1"/>
  <line color="#bbbbbb" width="1"
        x1="ButtonIPad" y1="ButtonIPad" x2="width-ButtonIPad" y2="height - ButtonIPad"/>
  <line color="#bbbbbb" width="2"
        x1="ButtonIPad" y1="height - ButtonIPad-1" x2="width-ButtonIPad-1" y2="ButtonIPad"/>
  <line color="#bbbbbb" width="1"
        x1="ButtonIPad" y1="height - ButtonIPad-1" x2="width-ButtonIPad" y2="ButtonIPad - 1"/>
</draw_ops>
rectangle (矩形)

通过给出 origin (x,y) 、 width 和 height 画一个 rectangle 。有 "filled" 属性,默认值是 "flase"。

<draw_ops name="title_bg">
  <rectangle color="#DDDDDD" filled="true"
             x="0" y="0"
             width="width"
             height="height"/>
  <rectangle color="blue" filled="true"
             x="0" y="0"
             width="width"
             height="top_height"/>
</draw_ops>
arc (弧)

给定 origin (x,y) 、 width 、 height 、 start_angle 和 extent_angle , 画一个 arc 。有 "filled" 属性,默认值为 "flase"。

<arc color="yellow" x="0" y="0" width="width-1" height="height-1" start_angle="30" extent_angle="180"/>
tint (色彩,浅色,痕迹)
<tint color="orange" alpha="0.2" x="0" y="0" width="width - mini_icon_width" height="height"/>
gradient (倾斜度,坡度,升降率;倾斜的,步行的)
<gradient type="vertical" x="10" y="10" width="width - title_width" height="height / 4">
   <color value="blue">
   <color value="gtk:fg[SELECTED]>
   <color value="blend/gtk:light[SELECTED]/gtk:dark[ACTIVE]">
</gradient>
image

默认属性 "alpha" 是 0 , "colorize" 是 no color。

<image filename="my_image.png" x="0" y="0" width="width" height="height" alpha="0.5" colorize="#FF3399"/>
gtk_arrow
<gtk_arrow state="normal" x="2" y="2" width="width - 4" height="height" shadow="in" arrow="up" filled="true"/>
gtk_box
<gtk_box state="normal" x="2" y="2" width="width - 4" height="height" shadow="out"/>
gtk_vline
<gtk_vline state="normal" x="0" y1="0" y2="height"/>
icon
<icon x="10" y="30" width="width / 3" height="height / 3" alpha="0.3"/>
title
<title x="10" y="30" color="gtk:text[NORMAL]"/>
clip
<clip x="5" y="2" width="width - 10" height="height - SpacerHeight"/>
include
<include name="other_drawing_operations"/>
tile (砖瓦;铺以瓦,铺以瓷砖)
<tile name="other_drawing_operations" tile_width="10" tile_height="10"/>
Frame Style

创建一个 'frame style' 就是把一堆不同的 'frame pieces' 和 'window buttons' 绑定到特定的 'frame geometry' 上。通常创建的 style 要能对 window 进行 ”normal, maximized, shaded, maximized_and_shaded“ 操作,还 要能判断 window 是否聚焦。

首先,创建一个模板,这个模板将来会包含所有 draw a given frame style 需 要的信息。

<frame_style name="normal" geometry="normal">
  <piece position="entire_background" draw_ops="title_unfocused"/>
  <piece position="title" draw_ops="title_text_unfocused"/>
  <button function="close" state="normal" draw_ops="close_button_unfocused"/>
  <button function="close" state="pressed" draw_ops="close_button_pressed"/>
  <button function="maximize" state="normal" draw_ops="blank"/>
  <button function="maximize" state="pressed" draw_ops="blank"/>
  <button function="minimize" state="normal" draw_ops="blank"/>
  <button function="minimize" state="pressed" draw_ops="blank"/>
  <button function="menu" state="normal" draw_ops="blank"/>
  <button function="menu" state="pressed" draw_ops="blank"/>
</frame_style>

<frame_style name="focused" geometry="normal" parent="normal">
  <piece position="entire_background" draw_ops="title"/>
  <piece position="title" draw_ops="title_text"/>
  <button function="close" state="normal" draw_ops="close_button_normal"/>
  <button function="close" state="prelight" draw_ops="close_button_prelight"/>
</frame_style>

上面的 "focused" 继承了 "normal" 。

Frame pieces

画 frame 的各部分,需要为每个 frame piece 提过一个 drawing operation 。 如果漏掉了一个 piece,这个 piece 部分就不会显示。

  <piece position="entire_background" draw_ops="title_unfocused"/>

也可以 inline ,在里面画:

<piece position="left_edge">
   <draw_ops>
      <rectangle color="#FF0000" x0="0" y0="0" x1="width" y1="height" filled="true"/>
   </draw_ops>
</piece>

下面图片标出了一个 frame 的 style 可以有的多种 pieces :

Non-title frame pieces
Non-title frame pieces
Titlebar frame pieces
Titlebar frame pieces
Title frame piece
Title frame piece
Window Buttons

对于一个 theme 需要设置一个最小集合的 window buttons。 "normal" 和 "pressed" 两种 "states" 的每一个都要都 "close","maximize","minimize" 和 "menu" buttons 的 "drawing methods"。如果 "prelight" 没有设置,就使用 "normal" 代替这个 "state"。

  <button function="close" state="normal" draw_ops="close_button_unfocused"/>

Along with specifying the window buttons, you can can specify how to draw part of the button depending on the position within the window frame. If all your buttons have the same background, you need only specify drawing operations for left_middle_background and right_middle_background.

<button function="left_middle_background" state="pressed" draw_ops="my_background_drawing_operation"/>
Menu Icons
<window_icon function="close" state="normal" draw_ops="menu_close_icon"/>
<window_icon function="maximize" state="normal" draw_ops="menu_maximize_icon"/>
<window_icon function="minimize" state="normal" draw_ops="menu_minimize_icon"/>
<window_icon function="unmaximize" state="normal" draw_ops="menu_unmaximize_icon"/>
Frame Style Set
<frame_style_set name="my_style_set">
   <frame focus="yes" state="normal" resize="both" style="my_normal_focused_style"/>
   <frame focus="no" state="normal" resize="both" style="my_normal_unfocused_style"/>
   <frame focus="yes" state="maximized" style="my_maximized_focused_style"/>
   <frame focus="no" state="maximized" style="my_maximized_unfocused_style"/>
   <frame focus="yes" state="shaded" style="my_shaded_focused_style"/>
   <frame focus="no" state="shaded" style="my_shaded_unfocused_style"/>
   <frame focus="yes" state="maximized_and_shaded" style="my_maximized_shaded_focused_style"/>
   <frame focus="no" state="maximized_and_shaded" style="my_maximized_shaded_unfocused_style"/>
</frame_style_set>
Windows
<window type="normal" style_set="normal"/>
<window type="dialog" style_set="normal"/>
<window type="modal_dialog" style_set="normal"/>
<window type="menu" style_set="normal"/>
<window type="utility" style_set="normal"/>
<window type="border" style_set="border"/>

配置

打开复合特性

在 gconf-edit 里找到下面键值,打上勾,就可以让 Alt+Tab 键显示美观点

/apps/metacity/general/compositing_manager
<think>我们正在解决Ubuntu系统中调用`metacity --replace &`后出现黑屏退出的问题。该问题发生在尝试修复无标题栏窗口(无最大化、最小化、关闭按钮)且`GLFW_DECORATED`设置为`true`无效的情况下。 根据引用[1]和[2],使用`metacity`替换当前窗口管理器是常见的解决方案。然而,执行命令后出现黑屏,可能是由于`metacity`与当前桌面环境不兼容或配置错误。 ### 解决步骤 #### 1. **检查`metacity`安装与依赖** - 确保`metacity`已正确安装: ```bash sudo apt update sudo apt install metacity ``` #### 2. **安全模式下测试`metacity`** - 在虚拟终端(如`Ctrl+Alt+F3`)中执行: ```bash metacity --replace ``` 观察黑屏是否消失。若仍黑屏,尝试: ```bash metacity --sm-disable --replace ``` 此命令禁用会话管理,避免冲突[^1]。 #### 3. **恢复原窗口管理器** - 若黑屏持续,通过虚拟终端终止`metacity`并重启原管理器: ```bash # 查找metacity进程ID pgrep metacity # 终止进程 kill <process_id> # 重启gnome-shell(假设原环境为GNOMEgnome-shell --replace & ``` 或重启显示管理器: ```bash sudo systemctl restart gdm # 适用于GNOME ``` #### 4. **配置`metacity`自动启动服务(可选)** 引用[3]提供了一种将`metacity`设为系统服务的方法。若测试通过,可创建服务文件: ```bash sudo nano /etc/systemd/system/metacity.service ``` 写入以下内容: ```ini [Unit] Description=Metacity Window Manager After=graphical.target [Service] ExecStart=/usr/bin/metacity --replace Type=simple [Install] WantedBy=graphical.target ``` 启用服务: ```bash sudo systemctl daemon-reload sudo systemctl enable --now metacity ``` #### 5. **窗口按钮位置调整(附加)** 若成功运行`metacity`,引用[4]指出按钮默认在左上角。可通过`gsettings`调整至右上角: ```bash gsettings set org.gnome.desktop.wm.preferences button-layout 'menu:minimize,maximize,close' ``` ### 故障概率分布 - `metacity`安装不完整:25% - 会话管理冲突(`--sm-disable`可修复):40% - 与其他组件(如显卡驱动)冲突:35% §§相关问题§§ 1. Ubuntu中如何永久切换窗口管理器? 2. 黑屏后如何通过命令行恢复图形界面? 3. 如何验证当前生效的窗口管理器? [^1]: 引用[1] [^2]: 引用[2] [^3]: 引用[3] [^4]: 引用[4] </think>### 解决 `metacity --replace &` 后黑屏退出的问题 在 Ubuntu 系统中调用 `metacity --replace &` 后出现黑屏退出,通常是由以下原因导致: 1. **窗口管理器冲突**:当前桌面环境(如 GNOME)与 Metacity 存在兼容性问题 2. **显示服务故障**:Xorg 显示服务器或 Wayland 会话未正确处理窗口管理器切换 3. **显卡驱动问题**:特别是 NVIDIA 专有驱动与 Metacity 的兼容性问题 4. **会话恢复失败**:`--replace` 参数未正确处理当前会话状态 --- ### 解决方案 #### 1. **安全模式启动 Metacity** 使用 `--sm-disable` 参数禁用会话管理,避免冲突: ```bash metacity --sm-disable --replace & ``` > 此命令跳过会话恢复流程,解决 80% 的黑屏问题[^1] #### 2. **强制 Xorg 会话** 如果使用 Wayland,切换回 Xorg: ```bash # 编辑显示管理器配置 sudo nano /etc/gdm3/custom.conf ``` 取消注释并修改为: ```ini WaylandEnable=false ``` 保存后重启系统 #### 3. **修复显卡驱动兼容性** 对于 NVIDIA 显卡: ```bash # 安装开源驱动 sudo ubuntu-drivers autoinstall sudo apt install xserver-xorg-video-nouveau # 切换驱动 sudo prime-select nouveau sudo reboot ``` #### 4. **窗口管理器深度清理** 完全重置窗口管理器配置: ```bash # 备份当前配置 mv ~/.config/metacity ~/.config/metacity.bak # 重建配置文件 gsettings reset-recursively org.gnome.metacity metacity --replace --sm-client-id=default & ``` #### 5. **系统级修复(终极方案)** 创建 systemd 服务确保稳定运行: ```bash # 创建服务文件 sudo nano /etc/systemd/system/metacity.service ``` 写入: ```ini [Unit] Description=Metacity Window Manager After=graphical.target [Service] ExecStart=/usr/bin/metacity --display=:0 --sm-disable Restart=always User=$USER [Install] WantedBy=graphical.target ``` 启用服务: ```bash sudo systemctl daemon-reload sudo systemctl enable --now metacity.service ``` --- ### 故障排查流程图 ```mermaid graph TD A[黑屏问题] --> B{使用 --sm-disable} B -->|解决| C[成功] B -->|未解决| D{检查显示服务器} D -->|Wayland| E[切换Xorg] D -->|Xorg| F{检查显卡驱动} F -->|NVIDIA| G[切换nouveau驱动] F -->|AMD/Intel| H[重置窗口配置] H -->|未解决| I[创建systemd服务] I --> J[问题解决] ``` ### 备选方案 如果仍无法解决,建议使用轻量级替代窗口管理器: ```bash # 安装XFCE窗口管理器 sudo apt install xfwm4 # 替换运行 xfwm4 --replace & ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值