diff --git a/ChangeLog b/ChangeLog index 227fb31..319d4e0 100644 --- a/ChangeLog +++ b/ChangeLog @@ -9,6 +9,12 @@ * 。 **************************************************************************/ +2023年 09月 12日 星期二 11:18:06 CST gsm <406643764@qq.com> + * 發布第2.6.11版; + * 修復臨時窗口在某些情況下位置異常的缺陷; + * 修復半屏最大化後無法還原的缺陷; + * 支持第三方任務欄、分頁器等通過ClientMessage來執行各種最大化操作。 + 2023年 09月 10日 星期日 19:38:07 CST gsm <406643764@qq.com> * 發布第2.6.10版; * 全屏模式下臨時窗口標題欄改爲只顯示關閉按鈕; diff --git a/NEWS b/NEWS index df72eec..9177bd5 100644 --- a/NEWS +++ b/NEWS @@ -9,6 +9,11 @@ * 。 * ************************************************************************/ +第2.6.11版: + * 修復臨時窗口在某些情況下位置異常的缺陷; + * 修復半屏最大化後無法還原的缺陷; + * 支持第三方任務欄、分頁器等執行各种最大化操作。 + 第2.6.10版: * 全屏模式下臨時窗口標題欄改爲只顯示關閉按鈕; * 在對窗口執行移動、調整尺寸、最大化操作時,修復放置類型的變更策略; diff --git a/TODO b/TODO index 9c9378a..a21f046 100644 --- a/TODO +++ b/TODO @@ -9,6 +9,9 @@ * 。 * ************************************************************************/ +第2.6.11版的下一步的開發計劃: + * 修復快速调整窗口尺寸时窗口内出现残影的缺陷。 + 第2.6.10版的下一步的開發計劃: * 修復半屏最大化無法還原的缺陷。 diff --git a/man/en_GB/man1/gwm.1 b/man/en_GB/man1/gwm.1 index e01fc41..11679b0 100644 --- a/man/en_GB/man1/gwm.1 +++ b/man/en_GB/man1/gwm.1 @@ -12,7 +12,7 @@ ./" program. Otherwise, see . ./" ************************************************* ***************************/ -.TH gwm 1 September 2023 "gwm 2.6.9" gwm +.TH gwm 1 September 2023 "gwm 2.6.11" gwm . .SH NAME .B @@ -27,7 +27,7 @@ gwm (gsm's window manager), is an X11-based dynamic window manager written in C .PP The child windows of the X Window System are always located above the parent window in screen space, and the window opened later is always located above the brother window opened first in screen space; the newly opened window is always located on top of the screen space. This window order is called window stacking order. The stacking order can be adjusted. .PP -gwm virtualizes the physical screen into multiple logical screens, the so-called virtual desktops. Logically, for each virtual desktop, the screen space is divided into the following seven layers from bottom to top: root window layer, below layer, normal window layer, dock layer, above layer, full screen window layer; The screen is divided into taskbar and workarea from the plane. Among them, the normal window layer is divided into tile layer and float layer; the workarea of the tile layer is divided into main area, second area, and fixed area. This is just a logical layering, the purpose is to achieve visual layering. In fact, gwm achieves the layering effect by adjusting the stacking order of the windows, not by resetting the parent window for layering. A window on the upper layer will always block the window on the lower layer. gwm supports four window layout modes: full screen, tiling, stacking, and preview, which can be dynamically switched at runtime. Full screen mode does not display the taskbar, and other modes display the taskbar. The taskbar is consists of buttons on the left, a icon bar in the middle, and a status bar on the right. Buttons are used to achieve specific functions, and the text of each button from left to right is: 1, 2, 3, □, ▦, ▣, ▥, ■, ^. The icon bar is used to display the iconified window, click the iconified window to deiconify window. The status bar shows the name of the root window. +gwm virtualizes the physical screen into multiple logical screens, the so-called virtual desktops. Logically, for each virtual desktop, the screen space is divided into the following six layers from bottom to top: desktop layer, below layer, normal window layer, dock layer, above layer, full screen window layer; The screen is divided into taskbar and workarea from the plane. Among them, the normal window layer is divided into tile layer and float layer; the workarea of the tile layer is divided into main area, second area, and fixed area. This is just a logical layering, the purpose is to achieve visual layering. In fact, gwm achieves the layering effect by adjusting the stacking order of the windows, not by resetting the parent window for layering. A window on the upper layer will always block the window on the lower layer. gwm supports four window layout modes: full screen, tiling, stacking, and preview, which can be dynamically switched at runtime. Full screen mode does not display the taskbar, and other modes display the taskbar. The taskbar is consists of buttons on the left, a icon bar in the middle, and a status bar on the right. Buttons are used to achieve specific functions, and the text of each button from left to right is: 1, 2, 3, □, ▦, ▣, ▥, ■, ^. The icon bar is used to display the iconified window, click the iconified window to deiconify window. The status bar shows the name of the root window. .PP The windows mentioned below, unless otherwise specified, refer to the windows managed by this window manager. The current window mentioned below, unless otherwise specified, refer to the window under the current virtual desktop that is located at the top of the layer to which the window belongs and has the keyboard input focus. The following instructions or commands, unless otherwise specified, are limited to the current virtual desktop. .PP diff --git a/man/zh_CN/man1/gwm.1 b/man/zh_CN/man1/gwm.1 index 3a2bc98..e9d0648 100644 --- a/man/zh_CN/man1/gwm.1 +++ b/man/zh_CN/man1/gwm.1 @@ -9,7 +9,7 @@ ./" 。 ./" ************************************************************************/ -.TH gwm 1 2023年9月 "gwm 2.6.10" gwm +.TH gwm 1 2023年9月 "gwm 2.6.11" gwm . .SH 名称 .B @@ -24,7 +24,7 @@ gwm \- gwm(gsm's window manager),是一个用C语言编写的基于X11的 .PP X窗口系统的子窗口在屏幕空间上总是位于父窗口之上,而后打开的窗口在屏幕空间上总是位于先打开的兄弟窗口之上;最新打开的窗口在屏幕空间上总是位于最上层。这种窗口次序叫窗口堆叠次序,简称窗口叠次序。叠次序是可以调整的。 .PP -gwm把物理屏幕虚拟为多个逻辑屏幕,即所谓的虚拟桌面。在逻辑上,对于每个虚拟桌面,从下至上把屏幕空间分成以下七层:根窗口层、下层、普通窗口层、停靠层、上层、全屏窗口层;从平面上,又把屏幕分为任务栏和工作区域。其中,普通窗口层又分为平铺层和悬浮层;平铺层的工作区域又分为主区域、次区域、固定区域。这仅仅是逻辑上的分层,目的是为了实现视觉上的分层。实际上,gwm通过调整窗口的叠次序来实现分层效果,并非通过重设父窗口来进行分层。上一层的窗口总是会挡着其下一层的窗口。gwm支持全屏、平铺、堆叠、预览四种窗口布局模式,这些模式可以在运行时动态切换。全屏模式不显示任务栏,其他模式均显示任务栏。任务栏由左边的按钮、中间的缩微栏、右边的状态栏组成。按钮用于实现特定的功能,各按钮的文字从左至右依次为:1、2、3、□、▦、▣、▥、■、^。缩微栏用于显示缩微窗口,点击缩微窗口则去缩微窗口。状态栏显示根窗口名字。 +gwm把物理屏幕虚拟为多个逻辑屏幕,即所谓的虚拟桌面。在逻辑上,对于每个虚拟桌面,从下至上把屏幕空间分成以下六层:桌面层、下层、普通窗口层、停靠层、上层、全屏窗口层;从平面上,又把屏幕分为任务栏和工作区域。其中,普通窗口层又分为平铺层和悬浮层;平铺层的工作区域又分为主区域、次区域、固定区域。这仅仅是逻辑上的分层,目的是为了实现视觉上的分层。实际上,gwm通过调整窗口的叠次序来实现分层效果,并非通过重设父窗口来进行分层。上一层的窗口总是会挡着其下一层的窗口。gwm支持全屏、平铺、堆叠、预览四种窗口布局模式,这些模式可以在运行时动态切换。全屏模式不显示任务栏,其他模式均显示任务栏。任务栏由左边的按钮、中间的缩微栏、右边的状态栏组成。按钮用于实现特定的功能,各按钮的文字从左至右依次为:1、2、3、□、▦、▣、▥、■、^。缩微栏用于显示缩微窗口,点击缩微窗口则去缩微窗口。状态栏显示根窗口名字。 .PP 以下所说的窗口,除非特别说明,否则均指受本窗口管理器所管理的窗口。以下所说的当前窗口,除非特别说明,否则均指当前虚拟桌面下位于该窗口所属层顶部并获得键盘输入焦点的窗口。以下说明或者命令,除非特别说明,否则均限于当前虚拟桌面。 .PP diff --git a/man/zh_HK/man1/gwm.1 b/man/zh_HK/man1/gwm.1 index 297bef0..2bb6b19 100644 --- a/man/zh_HK/man1/gwm.1 +++ b/man/zh_HK/man1/gwm.1 @@ -9,7 +9,7 @@ ./" 。 ./" ************************************************************************/ -.TH gwm 1 2023年9月 "gwm 2.6.10" gwm +.TH gwm 1 2023年9月 "gwm 2.6.11" gwm . .SH 名稱 .B @@ -24,7 +24,7 @@ gwm(gsm's window manager),是一個用C語言編寫的基於X11的動態 .PP X窗口系統的子窗口在屏幕空間上總是位於父窗口之上,而後打開的窗口在屏幕空间上總是位於先打開的兄弟窗口之上;最新打开的窗口在屏幕空間上總是位於最上層。这种窗口次序叫窗口堆叠次序,简称窗口叠次序。叠次序是可以调整的。 .PP -gwm把物理屏幕虛擬爲多個邏輯屏幕,即所謂的虛擬桌面。在邏輯上,對於每個虛擬桌面,從下至上把屏幕空間分成以下七層:根窗口層、下層、普通窗口層、停靠層、上層、全屏窗口層;從平面上,又把屏幕分爲任務欄和工作區域。其中,普通窗口層又分爲平鋪層和懸浮層;平鋪層的工作區域又分爲主區域、次區区域、固定區区域。這僅僅是邏輯上的分層,目的是爲了實現視覺上的分層。實際上,gwm通過調整窗口的疊次序來實現分層效果,並非通過重設父窗口來進行分層。上一層的窗口總是會擋着其下一層的窗口。gwm支持全屏、平鋪、堆疊、預覽四種窗口布局模式,這些模式可以在運行時動態切換。全屏模式不顯示任務欄,其他模式均顯示任務欄。任務欄由左邊的按鈕、中間的縮微欄、右邊的狀態欄組成。按鈕用於實現特定的功能,各按鈕的文字從左至右依次爲:1、2、3、□、▦、▣、▥、■、^。縮微欄,用於顯示縮微窗口,點擊縮微窗口則去縮微窗口。狀態欄顯示根窗口名字。 +gwm把物理屏幕虛擬爲多個邏輯屏幕,即所謂的虛擬桌面。在邏輯上,對於每個虛擬桌面,從下至上把屏幕空間分成以下六層:桌面層、下層、普通窗口層、停靠層、上層、全屏窗口層;從平面上,又把屏幕分爲任務欄和工作區域。其中,普通窗口層又分爲平鋪層和懸浮層;平鋪層的工作區域又分爲主區域、次區区域、固定區区域。這僅僅是邏輯上的分層,目的是爲了實現視覺上的分層。實際上,gwm通過調整窗口的疊次序來實現分層效果,並非通過重設父窗口來進行分層。上一層的窗口總是會擋着其下一層的窗口。gwm支持全屏、平鋪、堆疊、預覽四種窗口布局模式,這些模式可以在運行時動態切換。全屏模式不顯示任務欄,其他模式均顯示任務欄。任務欄由左邊的按鈕、中間的縮微欄、右邊的狀態欄組成。按鈕用於實現特定的功能,各按鈕的文字從左至右依次爲:1、2、3、□、▦、▣、▥、■、^。縮微欄,用於顯示縮微窗口,點擊縮微窗口則去縮微窗口。狀態欄顯示根窗口名字。 .PP 以下所說的窗口,除非特別說明,否則均指受本窗口管理器所管理的窗口。以下所說的當前窗口,除非特別說明,否則均指當前虛擬桌面下位於該窗口所屬層頂部並獲得鍵盤輸入焦點的窗口。以下說明或者命令,除非特別說明,否則均限於當前虛擬桌面。 .PP diff --git a/po/en_GB/LC_MESSAGES/gwm.po b/po/en_GB/LC_MESSAGES/gwm.po index 4b2706e..ce65bed 100644 --- a/po/en_GB/LC_MESSAGES/gwm.po +++ b/po/en_GB/LC_MESSAGES/gwm.po @@ -5,9 +5,9 @@ # msgid "" msgstr "" -"Project-Id-Version: gwm 2.6.10\n" +"Project-Id-Version: gwm 2.6.11\n" "Report-Msgid-Bugs-To: 406643764@qq.com\n" -"POT-Creation-Date: 2023-08-23 19:15+0800\n" +"POT-Creation-Date: 2023-09-12 11:12+0800\n" "PO-Revision-Date: 2023-05-05 11:26+0800\n" "Last-Translator: gsm <406643764@qq.com>\n" "Language-Team: English (British) <(nothing)>\n" @@ -79,8 +79,8 @@ msgid "暫固定區開窗" msgstr "Fixed next" #: src/config.c:490 -msgid "暫懸浮區開窗" -msgstr "Floating next" +msgid "暫懸浮層開窗" +msgstr "Float next" #: src/config.c:492 msgid "增大主區容量" @@ -189,16 +189,16 @@ msgid "切換到固定區域" msgstr "To fixed area" #: src/config.c:540 -msgid "切換到懸浮區域" -msgstr "To floating area" +msgid "切換到懸浮層" +msgstr "To float layer" #: src/config.c:541 msgid "切換到圖符區域" msgstr "To icon area" #: src/config.c:542 -msgid "切換到懸浮區域並最大化窗口" -msgstr "Maximize window" +msgid "切換到懸浮層並最大化窗口" +msgstr "Float and max" #: src/config.c:543 msgid "關閉窗口" @@ -350,3 +350,6 @@ msgstr "Command execution error" #: src/misc.c:318 msgid "未能成功地爲命令創建新進程" msgstr "Failed to successfully create a new process for the command" + +#~ msgid "暫懸浮區開窗" +#~ msgstr "Floating next" diff --git a/po/zh_CN/LC_MESSAGES/gwm.po b/po/zh_CN/LC_MESSAGES/gwm.po index 7b6ac5e..77b480f 100644 --- a/po/zh_CN/LC_MESSAGES/gwm.po +++ b/po/zh_CN/LC_MESSAGES/gwm.po @@ -6,9 +6,9 @@ # msgid "" msgstr "" -"Project-Id-Version: gwm 2.6.10\n" +"Project-Id-Version: gwm 2.6.11\n" "Report-Msgid-Bugs-To: 406643764@qq.com\n" -"POT-Creation-Date: 2023-08-23 19:13+0800\n" +"POT-Creation-Date: 2023-09-12 11:11+0800\n" "PO-Revision-Date: 2023-05-05 09:56+0800\n" "Last-Translator: gsm <406643764@qq.com>\n" "Language-Team: Chinese (simplified) \n" @@ -79,8 +79,8 @@ msgid "暫固定區開窗" msgstr "暂固定区开窗" #: src/config.c:490 -msgid "暫懸浮區開窗" -msgstr "暂悬浮区开窗" +msgid "暫懸浮層開窗" +msgstr "暂悬浮层开窗" #: src/config.c:492 msgid "增大主區容量" @@ -189,16 +189,16 @@ msgid "切換到固定區域" msgstr "切换到固定区域" #: src/config.c:540 -msgid "切換到懸浮區域" -msgstr "切换到悬浮区域" +msgid "切換到懸浮層" +msgstr "切换到悬浮层" #: src/config.c:541 msgid "切換到圖符區域" msgstr "切换到图符区域" #: src/config.c:542 -msgid "切換到懸浮區域並最大化窗口" -msgstr "切换到悬浮区域并最大化窗口" +msgid "切換到懸浮層並最大化窗口" +msgstr "切换到悬浮层并最大化窗口" #: src/config.c:543 msgid "關閉窗口" diff --git a/src/client.c b/src/client.c index 55755b3..4984916 100644 --- a/src/client.c +++ b/src/client.c @@ -19,9 +19,9 @@ static bool should_float(WM *wm, Client *c); static bool have_rule(const Rule *r, Client *c); static void add_client_node(Client *head, Client *c); static void set_win_rect_by_attr(WM *wm, Client *c); -static void fix_win_pos(WM *wm, Client *c); static bool fix_win_pos_by_hint(Client *c); static void fix_win_pos_by_prop(WM *wm, Client *c); +static void set_transient_win_pos(Client *c); static void fix_win_pos_by_workarea(WM *wm, Client *c); static void fix_win_size(WM *wm, Client *c); static void fix_win_size_by_workarea(WM *wm, Client *c); @@ -197,7 +197,7 @@ static void set_win_rect_by_attr(WM *wm, Client *c) c->x=a.x, c->y=a.y, c->w=a.width, c->h=a.height; } -static void fix_win_pos(WM *wm, Client *c) +void fix_win_pos(WM *wm, Client *c) { if(!fix_win_pos_by_hint(c)) fix_win_pos_by_prop(wm, c), fix_win_pos_by_workarea(wm, c); @@ -220,7 +220,7 @@ static void fix_win_pos_by_prop(WM *wm, Client *c) c->y=wm->workarea.y+(wm->workarea.h-c->h)/2; } -void set_transient_win_pos(Client *c) +static void set_transient_win_pos(Client *c) { c->x=c->owner->x+(c->owner->w-c->w)/2; c->y=c->owner->y+(c->owner->h-c->h)/2; @@ -811,12 +811,16 @@ void deiconify_all_clients(WM *wm) void update_net_wm_state(WM *wm, Client *c) { Atom *a=wm->ewmh_atom; - unsigned long n=0, val[13]={0}; // 目前EWMH規範中NET_WM_STATE共有13種狀態 + unsigned long n=0, val[17]={0}; // 目前EWMH規範中NET_WM_STATE共有13種狀態,GWM自定義4種狀態 if(c->win_state.modal) val[n++]=a[NET_WM_STATE_MODAL]; if(c->win_state.sticky) val[n++]=a[NET_WM_STATE_STICKY]; if(c->win_state.vmax) val[n++]=a[NET_WM_STATE_MAXIMIZED_VERT]; if(c->win_state.hmax) val[n++]=a[NET_WM_STATE_MAXIMIZED_HORZ]; + if(c->win_state.tmax) val[n++]=a[GWM_WM_STATE_MAXIMIZED_TOP]; + if(c->win_state.bmax) val[n++]=a[GWM_WM_STATE_MAXIMIZED_BOTTOM]; + if(c->win_state.lmax) val[n++]=a[GWM_WM_STATE_MAXIMIZED_LEFT]; + if(c->win_state.rmax) val[n++]=a[GWM_WM_STATE_MAXIMIZED_RIGHT]; if(c->win_state.shaded) val[n++]=a[NET_WM_STATE_SHADED]; if(c->win_state.skip_taskbar) val[n++]=a[NET_WM_STATE_SKIP_TASKBAR]; if(c->win_state.skip_pager) val[n++]=a[NET_WM_STATE_SKIP_PAGER]; @@ -875,7 +879,7 @@ void max_client(WM *wm, Client *c, Max_way max_way) bool vmax=(c->h+2*bw+th == wh), hmax=(c->w+2*bw == ww), fmax=false; save_rect_of_client(c); - if(!c->win_state.vmax && !c->win_state.hmax) + if(!is_win_state_max(c)) c->old_place_type=c->place_type; switch(max_way) @@ -902,3 +906,9 @@ Place_type get_dest_place_type_for_move(WM *wm, Client *c) return DESKTOP(wm)->cur_layout==TILE && is_tile_client(wm, c) ? NORMAL_LAYER_FLOAT : c->place_type; } + +bool is_win_state_max(Client *c) +{ + return c->win_state.vmax || c->win_state.hmax || c->win_state.tmax + || c->win_state.bmax || c->win_state.lmax || c->win_state.rmax; +} diff --git a/src/client.h b/src/client.h index ecd6060..73df668 100644 --- a/src/client.h +++ b/src/client.h @@ -48,7 +48,7 @@ struct client_tag // 客戶窗口相關信息 void add_client(WM *wm, Window win); void fix_place_type(WM *wm); void set_default_win_rect(WM *wm, Client *c); -void set_transient_win_pos(Client *c); +void fix_win_pos(WM *wm, Client *c); void create_titlebar(WM *wm, Client *c); Rect get_title_area_rect(WM *wm, Client *c); int get_clients_n(WM *wm, Place_type type, bool count_tile, bool count_all_desktop); @@ -89,5 +89,6 @@ void restore_client(WM *wm, Client *c); bool is_tile_client(WM *wm, Client *c); void max_client(WM *wm, Client *c, Max_way max_way); Place_type get_dest_place_type_for_move(WM *wm, Client *c); +bool is_win_state_max(Client *c); #endif diff --git a/src/config.c b/src/config.c index eaf3e1a..41e1f46 100644 --- a/src/config.c +++ b/src/config.c @@ -487,7 +487,7 @@ static void config_act_center_item_text(WM *wm) SET_ACT_CENTER_ITEM_TEXT(wm, MAIN_NEW_BUTTON, _("暫主區開窗")); SET_ACT_CENTER_ITEM_TEXT(wm, SEC_NEW_BUTTON, _("暫次區開窗")); SET_ACT_CENTER_ITEM_TEXT(wm, FIX_NEW_BUTTON, _("暫固定區開窗")); - SET_ACT_CENTER_ITEM_TEXT(wm, FLOAT_NEW_BUTTON, _("暫懸浮區開窗")); + SET_ACT_CENTER_ITEM_TEXT(wm, FLOAT_NEW_BUTTON, _("暫懸浮層開窗")); SET_ACT_CENTER_ITEM_TEXT(wm, N_MAIN_UP_BUTTON, _("增大主區容量")); SET_ACT_CENTER_ITEM_TEXT(wm, N_MAIN_DOWN_BUTTON, _("减小主區容量")); @@ -537,9 +537,9 @@ static void config_tooltip(WM *wm) tooltip[SECOND_BUTTON] = _("切換到次要區域"); tooltip[MAIN_BUTTON] = _("切換到主要區域"); tooltip[FIXED_BUTTON] = _("切換到固定區域"); - tooltip[FLOAT_BUTTON] = _("切換到懸浮區域"); + tooltip[FLOAT_BUTTON] = _("切換到懸浮層"); tooltip[ICON_BUTTON] = _("切換到圖符區域"); - tooltip[MAX_BUTTON] = _("切換到懸浮區域並最大化窗口"); + tooltip[MAX_BUTTON] = _("切換到懸浮層並最大化窗口"); tooltip[CLOSE_BUTTON] = _("關閉窗口"); tooltip[DESKTOP1_BUTTON] = _("切換到虛擬桌面1"); tooltip[DESKTOP2_BUTTON] = _("切換到虛擬桌面2"); diff --git a/src/debug.c b/src/debug.c index 52ee14b..f950fa3 100644 --- a/src/debug.c +++ b/src/debug.c @@ -82,6 +82,10 @@ void print_net_wm_state(WM *wm, Window win) printf("sticky: %d\n", state.sticky); printf("vmax: %d\n", state.vmax); printf("hmax: %d\n", state.hmax); + printf("tmax: %d\n", state.hmax); + printf("bmax: %d\n", state.hmax); + printf("lmax: %d\n", state.hmax); + printf("rmax: %d\n", state.hmax); printf("shaded: %d\n", state.shaded); printf("skip_taskbar: %d\n", state.skip_taskbar); printf("skip_pager: %d\n", state.skip_pager); diff --git a/src/drawable.h b/src/drawable.h index 850158b..9909af2 100644 --- a/src/drawable.h +++ b/src/drawable.h @@ -46,6 +46,10 @@ typedef struct // 與_NET_WM_STATE列表相應的狀態標志 unsigned int below : 1; unsigned int attent : 1; unsigned int focused : 1; + unsigned int tmax : 1; + unsigned int bmax : 1; + unsigned int lmax : 1; + unsigned int rmax : 1; } Net_wm_state; Window get_transient_for(WM *wm, Window w); diff --git a/src/func.c b/src/func.c index dfdef86..bd3f38e 100644 --- a/src/func.c +++ b/src/func.c @@ -306,12 +306,20 @@ void max_restore_client(WM *wm, XEvent *e, Func_arg arg) if(c == wm->clients) return; - if(c->win_state.vmax || c->win_state.hmax) + if(is_win_state_max(c)) { if(c->win_state.vmax) c->win_state.vmax=0; if(c->win_state.hmax) c->win_state.hmax=0; + if(c->win_state.tmax) + c->win_state.tmax=0; + if(c->win_state.bmax) + c->win_state.bmax=0; + if(c->win_state.lmax) + c->win_state.lmax=0; + if(c->win_state.rmax) + c->win_state.rmax=0; restore_client(wm, c); } else @@ -331,10 +339,16 @@ void maximize_client(WM *wm, XEvent *e, Func_arg arg) return; max_client(wm, c, arg.max_way); - if(arg.max_way == IN_SITU_VERT_MAX) - c->win_state.vmax=1; - if(arg.max_way == IN_SITU_HORZ_MAX) - c->win_state.hmax=1; + switch(arg.max_way) + { + case IN_SITU_VERT_MAX: c->win_state.vmax=1; break; + case IN_SITU_HORZ_MAX: c->win_state.hmax=1; break; + case TOP_MAX: c->win_state.tmax=1; break; + case BOTTOM_MAX: c->win_state.bmax=1; break; + case LEFT_MAX: c->win_state.lmax=1; break; + case RIGHT_MAX: c->win_state.rmax=1; break; + case FULL_MAX: c->win_state.vmax=c->win_state.hmax=1; break; + } update_net_wm_state(wm, c); } diff --git a/src/gwm.h b/src/gwm.h index baf08df..e98de7f 100644 --- a/src/gwm.h +++ b/src/gwm.h @@ -124,6 +124,8 @@ "_NET_WM_OPAQUE_REGION", "_NET_WM_BYPASS_COMPOSITOR", "_NET_WM_PING", \ "_NET_WM_SYNC_REQUEST", "_NET_WM_FULLSCREEN_MONITORS", \ "_NET_WM_FULL_PLACEMENT", \ + "GWM_WM_STATE_MAXIMIZED_TOP", "GWM_WM_STATE_MAXIMIZED_BOTTOM", \ + "GWM_WM_STATE_MAXIMIZED_LEFT", "GWM_WM_STATE_MAXIMIZED_RIGHT", \ } typedef struct config_tag Config; @@ -175,7 +177,10 @@ enum ewmh_atom_tag // EWMH規範的標識符 NET_WM_USER_TIME, NET_WM_USER_TIME_WINDOW, NET_FRAME_EXTENTS, NET_WM_OPAQUE_REGION, NET_WM_BYPASS_COMPOSITOR, NET_WM_PING, NET_WM_SYNC_REQUEST, NET_WM_FULLSCREEN_MONITORS, - NET_WM_FULL_PLACEMENT, EWMH_ATOM_N + NET_WM_FULL_PLACEMENT, + GWM_WM_STATE_MAXIMIZED_TOP, GWM_WM_STATE_MAXIMIZED_BOTTOM, + GWM_WM_STATE_MAXIMIZED_LEFT, GWM_WM_STATE_MAXIMIZED_RIGHT, + EWMH_ATOM_N }; typedef enum ewmh_atom_tag Ewmh_atom; diff --git a/src/handler.c b/src/handler.c index fe72897..d63c2e9 100644 --- a/src/handler.c +++ b/src/handler.c @@ -26,6 +26,10 @@ static void change_net_wm_state_for_modal(WM *wm, Client *c, long act); static void change_net_wm_state_for_sticky(WM *wm, Client *c, long act); static void change_net_wm_state_for_vmax(WM *wm, Client *c, long act); static void change_net_wm_state_for_hmax(WM *wm, Client *c, long act); +static void change_net_wm_state_for_tmax(WM *wm, Client *c, long act); +static void change_net_wm_state_for_bmax(WM *wm, Client *c, long act); +static void change_net_wm_state_for_lmax(WM *wm, Client *c, long act); +static void change_net_wm_state_for_rmax(WM *wm, Client *c, long act); static void change_net_wm_state_for_shaded(WM *wm, Client *c, long act); static void change_net_wm_state_for_skip_taskbar(WM *wm, Client *c, long act); static void change_net_wm_state_for_skip_pager(WM *wm, Client *c, long act); @@ -179,6 +183,10 @@ static void change_net_wm_state(WM *wm, Client *c, long *full_act) if(mask.sticky) change_net_wm_state_for_sticky(wm, c, act); if(mask.vmax) change_net_wm_state_for_vmax(wm, c, act); if(mask.hmax) change_net_wm_state_for_hmax(wm, c, act); + if(mask.tmax) change_net_wm_state_for_tmax(wm, c, act); + if(mask.bmax) change_net_wm_state_for_bmax(wm, c, act); + if(mask.lmax) change_net_wm_state_for_lmax(wm, c, act); + if(mask.rmax) change_net_wm_state_for_rmax(wm, c, act); if(mask.shaded) change_net_wm_state_for_shaded(wm, c, act); if(mask.skip_taskbar) change_net_wm_state_for_skip_taskbar(wm, c, act); if(mask.skip_pager) change_net_wm_state_for_skip_pager(wm, c, act); @@ -203,6 +211,10 @@ static Net_wm_state get_net_wm_state_mask(WM *wm, long *full_act) else if(p == (long)a[NET_WM_STATE_STICKY]) m.sticky=1; else if(p == (long)a[NET_WM_STATE_MAXIMIZED_VERT]) m.vmax=1; else if(p == (long)a[NET_WM_STATE_MAXIMIZED_HORZ]) m.hmax=1; + else if(p == (long)a[GWM_WM_STATE_MAXIMIZED_TOP]) m.tmax=1; + else if(p == (long)a[GWM_WM_STATE_MAXIMIZED_BOTTOM]) m.bmax=1; + else if(p == (long)a[GWM_WM_STATE_MAXIMIZED_LEFT]) m.lmax=1; + else if(p == (long)a[GWM_WM_STATE_MAXIMIZED_RIGHT]) m.rmax=1; else if(p == (long)a[NET_WM_STATE_SHADED]) m.shaded=1; else if(p == (long)a[NET_WM_STATE_SKIP_TASKBAR]) m.skip_taskbar=1; else if(p == (long)a[NET_WM_STATE_SKIP_PAGER]) m.skip_pager=1; @@ -247,6 +259,38 @@ static void change_net_wm_state_for_hmax(WM *wm, Client *c, long act) max_client(wm, c, IN_SITU_HORZ_MAX), c->win_state.hmax=1; } +static void change_net_wm_state_for_tmax(WM *wm, Client *c, long act) +{ + if(SHOULD_REMOVE_STATE(c, act, tmax)) + restore_client(wm, c), c->win_state.tmax=0; + else + max_client(wm, c, TOP_MAX), c->win_state.tmax=1; +} + +static void change_net_wm_state_for_bmax(WM *wm, Client *c, long act) +{ + if(SHOULD_REMOVE_STATE(c, act, bmax)) + restore_client(wm, c), c->win_state.bmax=0; + else + max_client(wm, c, BOTTOM_MAX), c->win_state.bmax=1; +} + +static void change_net_wm_state_for_lmax(WM *wm, Client *c, long act) +{ + if(SHOULD_REMOVE_STATE(c, act, lmax)) + restore_client(wm, c), c->win_state.lmax=0; + else + max_client(wm, c, LEFT_MAX), c->win_state.lmax=1; +} + +static void change_net_wm_state_for_rmax(WM *wm, Client *c, long act) +{ + if(SHOULD_REMOVE_STATE(c, act, rmax)) + restore_client(wm, c), c->win_state.rmax=0; + else + max_client(wm, c, RIGHT_MAX), c->win_state.rmax=1; +} + /* 暫不支持窗口陰影特效 */ static void change_net_wm_state_for_shaded(WM *wm, Client *c, long act) { diff --git a/src/layout.c b/src/layout.c index 5176fd2..15586da 100644 --- a/src/layout.c +++ b/src/layout.c @@ -123,7 +123,7 @@ static void set_rect_of_transient_win_for_tiling(WM *wm) { for(Client *c=wm->clients->next; c!=wm->clients; c=c->next) if(is_on_cur_desktop(wm, c) && c->owner) - set_transient_win_pos(c); + fix_win_pos(wm, c); } static void get_area_size(WM *wm, int *mw, int *mh, int *sw, int *sh, int *fw, int *fh)