* 發布第2.10.13版;

* 修復set_fullscreen函數未更新win_state的缺陷;
        * 移動或調整窗口尺寸之後直接取消最大化狀態;
        * mvresize.c與minimax.c解耦。
This commit is contained in:
gsm 2024-09-25 12:38:52 +08:00
parent e4ffa459c6
commit 7a1874935e
26 changed files with 227 additions and 206 deletions

View File

@ -9,6 +9,12 @@
* <http://www.gnu.org/licenses/>。
**************************************************************************/
2024年 09月 25日 星期三 12:26:41 HKT gsm <406643764@qq.com>
* 發布第2.10.13版;
* 修復set_fullscreen函數未更新win_state的缺陷
* 移動或調整窗口尺寸之後直接取消最大化狀態;
* mvresize.c與minimax.c解耦。
2024年 09月 05日 星期四 12:13:15 HKT gsm <406643764@qq.com>
* 發布第2.10.12版;
* 修復desktop_mask引發段錯誤的缺陷

4
NEWS
View File

@ -9,6 +9,10 @@
* <http://www.gnu.org/licenses/>。
* ************************************************************************/
第2.10.13版:
* 修復無法取消窗口全屏狀態的缺陷;
* 移動或調整窗口尺寸之後直接取消最大化狀態。
第2.10.12版:
* 修復偶爾崩潰的缺陷;
* gwm內部桌面編號改爲從0起算。

5
TODO
View File

@ -9,6 +9,11 @@
* <http://www.gnu.org/licenses/>。
* ************************************************************************/
第2.10.13版的下一步的開發計劃:
* 修復某些臨時窗口位置和尺寸異常的缺陷;
* 優化構件狀態與顏色之間的關系;
* 修復堆疊模式下窗口疊次序不合理的問題。
第2.10.12版的下一步的開發計劃:
* 修復某些臨時窗口位置和尺寸異常的缺陷;
* 優化構件狀態與顏色之間的關系。

View File

@ -12,7 +12,7 @@
./" program. Otherwise, see <http://www.gnu.org/licenses/>.
./" ************************************************* ***************************/
.TH gwm 1 July 2024 "gwm 2.10.12" gwm
.TH gwm 1 September 2024 "gwm 2.10.13" gwm
.
.SH NAME
.B

View File

@ -9,7 +9,7 @@
./" <http://www.gnu.org/licenses/>。
./" ************************************************************************/
.TH gwm 1 20247月 "gwm 2.10.12" gwm
.TH gwm 1 20249月 "gwm 2.10.13" gwm
.
.SH 名称
.B

View File

@ -9,7 +9,7 @@
./" <http://www.gnu.org/licenses/>。
./" ************************************************************************/
.TH gwm 1 20247月 "gwm 2.10.12" gwm
.TH gwm 1 20249月 "gwm 2.10.13" gwm
.
.SH 名稱
.B

View File

@ -5,9 +5,9 @@
#
msgid ""
msgstr ""
"Project-Id-Version: gwm 2.10.12\n"
"Project-Id-Version: gwm 2.10.13\n"
"Report-Msgid-Bugs-To: 406643764@qq.com\n"
"POT-Creation-Date: 2024-09-05 12:15+0800\n"
"POT-Creation-Date: 2024-09-25 12:36+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"
@ -17,7 +17,7 @@ msgstr ""
"Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
#: client.c:662
#: client.c:670
msgid "錯誤:查詢窗口清單失敗!"
msgstr "Error: Failed to query window list!"
@ -338,17 +338,17 @@ msgstr "Error: There is already another window manager running!"
msgid "X錯誤資源號=%#lx, 請求量=%lu, 錯誤碼=%d, 主請求碼=%d, 次請求碼=%d\n"
msgstr "X error: Resource number=%#lx, Request number=%lu, Error code=%d, Major request code=%d, Minor request code=%d\n"
#: widget.c:212
#: widget.c:218
#, c-format
msgid "錯誤窗口0x%lx輸入法設置失敗"
msgstr "Error: Window (0x%lx) input method setup failed!"
#: widget.c:319
#: widget.c:325
#, c-format
msgid "錯誤:找不到指定的鍵符號相應的功能轉換鍵!\n"
msgstr "Error: The corresponding modifier key for the specified key symbol could not be found!\n"
#: widget.c:322
#: widget.c:328
#, c-format
msgid "錯誤:指定的鍵符號不存在對應的鍵代碼!\n"
msgstr "Error: The key symbol specified does not have a corresponding key code!\n"

View File

@ -6,9 +6,9 @@
#
msgid ""
msgstr ""
"Project-Id-Version: gwm 2.10.12\n"
"Project-Id-Version: gwm 2.10.13\n"
"Report-Msgid-Bugs-To: 406643764@qq.com\n"
"POT-Creation-Date: 2024-09-05 12:15+0800\n"
"POT-Creation-Date: 2024-09-25 12:36+0800\n"
"PO-Revision-Date: 2023-05-05 09:56+0800\n"
"Last-Translator: gsm <406643764@qq.com>\n"
"Language-Team: Chinese (simplified) <i18n-zh@googlegroups.com>\n"
@ -17,7 +17,7 @@ msgstr ""
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
#: client.c:662
#: client.c:670
msgid "錯誤:查詢窗口清單失敗!"
msgstr "错误:查询窗口列表失败!"
@ -338,17 +338,17 @@ msgstr "错误:已经有其他窗口管理器在运行!"
msgid "X錯誤資源號=%#lx, 請求量=%lu, 錯誤碼=%d, 主請求碼=%d, 次請求碼=%d\n"
msgstr "X错误资源号=%#lx请求量=%lu错误码=%d主请求码=%d次请求码=%d\n"
#: widget.c:212
#: widget.c:218
#, c-format
msgid "錯誤窗口0x%lx輸入法設置失敗"
msgstr "错误窗口0x%lx输入法设置失败"
#: widget.c:319
#: widget.c:325
#, c-format
msgid "錯誤:找不到指定的鍵符號相應的功能轉換鍵!\n"
msgstr "错误:找不到指定的键符号相应的功能转换键!\n"
#: widget.c:322
#: widget.c:328
#, c-format
msgid "錯誤:指定的鍵符號不存在對應的鍵代碼!\n"
msgstr "错误:指定的键符号不存在对应的键代码!\n"

View File

@ -173,16 +173,10 @@ static void set_default_place_type(Client *c)
else if(c->win_type.dock) c->place_type = DOCK_LAYER;
else if(c->win_state.above) c->place_type = ABOVE_LAYER;
else if(c->win_state.fullscreen) c->place_type = FULLSCREEN_LAYER;
else if(is_win_state_max(c)) c->place_type = FLOAT_LAYER;
else if(is_win_state_max(c->win_state)) c->place_type = FLOAT_LAYER;
else c->place_type = TILE_LAYER_MAIN;
}
void set_win_rect_by_frame(Client *c)
{
Rect r=get_frame_rect_by_win(c->frame, WIDGET_X(c), WIDGET_Y(c), WIDGET_W(c), WIDGET_H(c));
WIDGET_X(c)=r.x, WIDGET_Y(c)=r.y, WIDGET_W(c)=r.w, WIDGET_H(c)=r.h;
}
static void set_default_win_rect(Client *c)
{
WIDGET_W(c)=xinfo.screen_width/4;
@ -529,6 +523,11 @@ bool is_tile_client(Client *c)
&& is_normal_layer(c->place_type);
}
bool is_tiled_client(Client *c)
{
return get_gwm_current_layout()==TILE && is_tile_client(c);
}
/* 獲取當前桌面按從早到遲的映射順序排列的客戶窗口列表 */
Window *get_client_win_list(Client *clients, int *n)
{
@ -645,6 +644,15 @@ void update_client_bg(WM *wm, unsigned int desktop_n, Client *c)
update_frame_bg(c->frame);
}
void move_resize_client(Client *c, const Delta_rect *d)
{
if(d)
WIDGET_X(c)+=d->dx, WIDGET_Y(c)+=d->dy, WIDGET_W(c)+=d->dw, WIDGET_H(c)+=d->dh;
set_frame_rect_by_client(c);
move_resize_frame(c->frame, WIDGET_X(c->frame), WIDGET_Y(c->frame), WIDGET_W(c->frame), WIDGET_H(c->frame));
XResizeWindow(xinfo.display, WIDGET_WIN(c), WIDGET_W(c), WIDGET_H(c));
}
/* 生成帶表頭結點的雙向循環鏈表 */
void create_clients(WM *wm)
{
@ -668,3 +676,32 @@ void create_clients(WM *wm)
}
XFree(child);
}
void set_client_rect_by_outline(Client *c, int x, int y, int w, int h)
{
int bw=WIDGET_BORDER_W(c->frame);
set_widget_rect(WIDGET(c->frame), x, y, w-2*bw, h-2*bw);
set_client_rect_by_frame(c);
}
void set_frame_rect_by_client(Client *c)
{
int bw=WIDGET_BORDER_W(c->frame),
bh=get_frame_titlebar_height(c->frame),
x=WIDGET_X(c)-bw,
y=WIDGET_Y(c)-bh-bw,
w=WIDGET_W(c),
h=WIDGET_H(c)+bh;
set_widget_rect(WIDGET(c->frame), x, y, w, h);
}
void set_client_rect_by_frame(Client *c)
{
int bw=WIDGET_BORDER_W(c->frame),
bh=get_frame_titlebar_height(c->frame),
x=WIDGET_X(c->frame)+bw,
y=WIDGET_Y(c->frame)+bh+bw,
w=WIDGET_W(c->frame),
h=WIDGET_H(c->frame)-bh;
set_widget_rect(WIDGET(c), x, y, w, h);
}

View File

@ -41,7 +41,6 @@ struct client_tag // 客戶窗口相關信息
void add_client(WM *wm, Window win);
void set_all_net_client_list(Client *clients);
void set_win_rect_by_frame(Client *c);
Rect get_title_area_rect(Client *c);
int get_clients_n(Client *clients, Place_type type, bool count_icon, bool count_trans, bool count_all_desktop);
bool is_iconic_client(Client *c);
@ -62,6 +61,7 @@ void save_place_info_of_clients(Client *clients);
void restore_place_info_of_client(Client *c);
void restore_place_info_of_clients(Client *clients);
bool is_tile_client(Client *c);
bool is_tiled_client(Client *c);
Window *get_client_win_list(Client *clients, int *n);
Window *get_client_win_list_stacking(Client *clients, int *n);
void set_state_attent(Client *c, bool attent);
@ -69,8 +69,12 @@ bool is_wm_win(Client *clients, Window win, bool before_wm);
void restack_win(WM *wm, Window win);
void update_clients_bg(WM *wm);
void update_client_bg(WM *wm, unsigned int desktop_n, Client *c);
void move_resize_client(Client *c, const Delta_rect *d);
void create_clients(WM *wm);
void add_subgroup(Client *head, Client *subgroup_leader);
void del_subgroup(Client *subgroup_leader);
void set_client_rect_by_outline(Client *c, int x, int y, int w, int h);
void set_client_rect_by_frame(Client *c);
void set_frame_rect_by_client(Client *c);
#endif

View File

@ -387,7 +387,7 @@ static void config_misc(void)
cfg->default_n_main_max=1;
cfg->act_center_col=4;
cfg->font_pad_ratio=0.25;
cfg->default_main_area_ratio=0.6;
cfg->default_main_area_ratio=0.533;
cfg->default_fixed_area_ratio=0.15;
cfg->autostart="~/.config/gwm/autostart.sh";
cfg->cur_icon_theme="default";

View File

@ -316,6 +316,12 @@ void update_net_wm_state(Window win, Net_wm_state state)
replace_atom_prop(win, prop, states, n);
}
void update_net_wm_state_for_no_max(Window win, Net_wm_state state)
{
state.vmax=state.hmax=state.tmax=state.bmax=state.lmax=state.rmax=0;
update_net_wm_state(win, state);
}
Net_wm_state get_net_wm_state_mask(const long *full_act)
{
Net_wm_state m={0};
@ -345,6 +351,12 @@ Net_wm_state get_net_wm_state_mask(const long *full_act)
return m;
}
bool is_win_state_max(Net_wm_state state)
{
return state.vmax || state.hmax || state.tmax
|| state.bmax || state.lmax || state.rmax;
}
/* 判斷是否存在遵從EWMH標準的合成器 */
bool have_compositor(void)
{

View File

@ -119,7 +119,9 @@ void set_net_wm_allowed_actions(Window win);
Net_wm_win_type get_net_wm_win_type(Window win);
Net_wm_state get_net_wm_state(Window win);
void update_net_wm_state(Window win, Net_wm_state state);
void update_net_wm_state_for_no_max(Window win, Net_wm_state state);
Net_wm_state get_net_wm_state_mask(const long *full_act);
bool is_win_state_max(Net_wm_state state);
bool have_compositor(void);
Window get_compositor(void);
char *get_net_wm_name(Window win);

View File

@ -151,18 +151,6 @@ void move_resize_frame(Frame *frame, int x, int y, int w, int h)
move_resize_widget(WIDGET(frame), x, y, w, h);
}
Rect get_frame_rect_by_win(const Frame *frame, int x, int y, int w, int h)
{
int bw=frame->base.border_w, bh=(frame->titlebar ? WIDGET_H(frame->titlebar) : 0);
return (Rect){x-bw, y-bh-bw, w, h+bh};
}
Rect get_win_rect_by_frame(const Frame *frame)
{
int bw=frame->base.border_w, bh=(frame->titlebar ? WIDGET_H(frame->titlebar) : 0);
return (Rect){WIDGET_X(frame)+bw, WIDGET_Y(frame)+bh+bw, WIDGET_W(frame), WIDGET_H(frame)-bh};
}
bool is_frame_part(const Frame *frame, Window win)
{
if(win == WIDGET_WIN(frame))
@ -211,9 +199,9 @@ Menu *get_frame_menu(const Frame *frame)
return (frame && frame->titlebar) ? frame->titlebar->menu : NULL;
}
Titlebar *get_frame_titlebar(const Frame *frame)
int get_frame_titlebar_height(const Frame *frame)
{
return frame->titlebar;
return frame->titlebar ? WIDGET_H(frame->titlebar) : 0;
}
void toggle_titlebar(Frame *frame, const char *title, Imlib_Image image)

View File

@ -23,13 +23,11 @@ typedef struct rectangle_tag Rect;
Frame *create_frame(Widget *parent, Widget_state state, int x, int y, int w, int h, int titlebar_h, int border_w, const char *title, Imlib_Image image);
void destroy_frame(Frame *frame);
void move_resize_frame(Frame *frame, int x, int y, int w, int h);
Rect get_frame_rect_by_win(const Frame *frame, int x, int y, int w, int h);
Rect get_win_rect_by_frame(const Frame *frame);
bool is_frame_part(const Frame *frame, Window win);
void set_frame_state_current(Frame *frame, int value);
void update_frame_bg(const Frame *frame);
Menu *get_frame_menu(const Frame *frame);
Titlebar *get_frame_titlebar(const Frame *frame);
int get_frame_titlebar_height(const Frame *frame);
void toggle_titlebar(Frame *frame, const char *title, Imlib_Image image);
void update_titlebar_fg(const Widget *widget);
void update_titlebar_layout(const Frame *frame);

View File

@ -51,7 +51,7 @@ bool get_valid_click(WM *wm, Pointer_act act, XEvent *oe, XEvent *ne)
do
{
XMaskEvent(xinfo.display, ROOT_EVENT_MASK|POINTER_MASK, p);
wm->event_handlers[p->type](wm, p);
wm->handle_event(wm, p);
}while(!is_match_button_release(oe, p));
if(act != NO_OP)
XUngrabPointer(xinfo.display, CurrentTime);

View File

@ -96,6 +96,11 @@ struct rectangle_tag // 矩形窗口或區域的坐標和尺寸
};
typedef struct rectangle_tag Rect;
typedef struct /* 調整窗口尺寸的信息 */
{
int dx, dy, dw, dh; /* 分別爲窗口坐標和尺寸的變化量 */
} Delta_rect;
enum layout_tag // 窗口管理器的布局模式
{
PREVIEW, STACK, TILE,
@ -118,6 +123,9 @@ typedef enum // 窗口疊次序分層類型
FULLSCREEN_TOP, TOP_WIN_TYPE_N
} Top_win_type;
typedef struct wm_tag WM;
typedef void (*event_handler_type)(WM*, XEvent *); // 事件處理器類型
struct wm_tag // 窗口管理器相關信息
{
Desktop *desktop[DESKTOP_N]; // 虛擬桌面
@ -126,9 +134,8 @@ struct wm_tag // 窗口管理器相關信息
Window top_wins[TOP_WIN_TYPE_N]; // 窗口疊次序分層參照窗口列表,即分層層頂窗口
Client *clients; // 頭結點
Strings *wallpapers, *cur_wallpaper; // 壁紙文件列表、当前壁纸文件
void (*event_handlers[LASTEvent])(struct wm_tag*, XEvent *); // 事件處理器數組
event_handler_type handle_event; // 事件處理器
};
typedef struct wm_tag WM;
enum direction_tag // 方向
{

View File

@ -26,7 +26,7 @@
#include "widget.h"
#include "handler.h"
static void ignore_event(WM *wm, XEvent *e);
static void handle_event(WM *wm, XEvent *e);
static void handle_button_press(WM *wm, XEvent *e);
static void handle_button_release(WM *wm, XEvent *e);
static void unmap_for_click(WM *wm, Widget_id id);
@ -65,40 +65,43 @@ static void handle_wm_name_notify(WM *wm, Window win, Atom atom);
static void handle_wm_transient_for_notify(WM *wm, Window win);
static void handle_selection_notify(WM *wm, XEvent *e);
static event_handler_type event_handlers[LASTEvent]; // 事件處理器數組
void handle_events(WM *wm)
{
XEvent e;
XSync(xinfo.display, False);
while(run_flag && !XNextEvent(xinfo.display, &e))
if(!XFilterEvent(&e, None))
wm->event_handlers[e.type](wm, &e);
handle_event(wm, &e);
clear_wm(wm);
}
static void handle_event(WM *wm, XEvent *e)
{
if(!XFilterEvent(e, None) && event_handlers[e->type])
event_handlers[e->type](wm, e);
}
void reg_event_handlers(WM *wm)
{
for(int i=0; i<LASTEvent; i++)
wm->event_handlers[i]=ignore_event;
event_handlers[i]=NULL;
wm->handle_event=handle_event;
wm->event_handlers[ButtonPress] = handle_button_press;
wm->event_handlers[ButtonRelease] = handle_button_release;
wm->event_handlers[ClientMessage] = handle_client_message;
wm->event_handlers[ConfigureRequest] = handle_config_request;
wm->event_handlers[EnterNotify] = handle_enter_notify;
wm->event_handlers[Expose] = handle_expose;
wm->event_handlers[FocusIn] = handle_focus_in;
wm->event_handlers[FocusOut] = handle_focus_out;
wm->event_handlers[KeyPress] = handle_key_press;
wm->event_handlers[LeaveNotify] = handle_leave_notify;
wm->event_handlers[MapRequest] = handle_map_request;
wm->event_handlers[UnmapNotify] = handle_unmap_notify;
wm->event_handlers[PropertyNotify] = handle_property_notify;
wm->event_handlers[SelectionNotify] = handle_selection_notify;
}
static void ignore_event(WM *wm, XEvent *e)
{
UNUSED(wm), UNUSED(e);
event_handlers[ButtonPress] = handle_button_press;
event_handlers[ButtonRelease] = handle_button_release;
event_handlers[ClientMessage] = handle_client_message;
event_handlers[ConfigureRequest] = handle_config_request;
event_handlers[EnterNotify] = handle_enter_notify;
event_handlers[Expose] = handle_expose;
event_handlers[FocusIn] = handle_focus_in;
event_handlers[FocusOut] = handle_focus_out;
event_handlers[KeyPress] = handle_key_press;
event_handlers[LeaveNotify] = handle_leave_notify;
event_handlers[MapRequest] = handle_map_request;
event_handlers[UnmapNotify] = handle_unmap_notify;
event_handlers[PropertyNotify] = handle_property_notify;
event_handlers[SelectionNotify] = handle_selection_notify;
}
static void handle_button_press(WM *wm, XEvent *e)
@ -151,7 +154,7 @@ static bool is_func_click(const Widget_id id, const Buttonbind *b, XEvent *e)
{
return (b->widget_id == id
&& b->button == e->xbutton.button
&& is_equal_modifier_mask( b->modifier, e->xbutton.state));
&& is_equal_modifier_mask(b->modifier, e->xbutton.state));
}
static void handle_button_release(WM *wm, XEvent *e)
@ -413,7 +416,7 @@ static void handle_pointer_hover(WM *wm, const Widget *widget)
if(XPending(xinfo.display))
{
XNextEvent(xinfo.display, &ev);
wm->event_handlers[ev.type](wm, &ev);
handle_event(wm, &ev);
if(ev.type == MotionNotify && ev.xmotion.window==widget->win)
t=t0, show=false;
else if(ev.type==LeaveNotify && ev.xcrossing.window==widget->win)

View File

@ -13,8 +13,8 @@
#include "layout.h"
#include "prop.h"
#include "icccm.h"
#include "ewmh.h"
#include "minimax.h"
#include "mvresize.h"
#include "taskbar.h"
static void fix_win_rect(WM *wm, Client *c);
@ -76,8 +76,7 @@ static void fix_win_size_by_workarea(WM *wm, Client *c)
WIDGET_W(c->frame)=ww-2*bw;
if(WIDGET_H(c->frame)+2*bw > wh)
WIDGET_H(c->frame)=wh-2*bw;
Rect r=get_win_rect_by_frame(c->frame);
WIDGET_W(c)=r.w, WIDGET_H(c)=r.h;
set_client_rect_by_frame(c);
}
static void fix_win_pos(WM *wm, Client *c, const XSizeHints *hint)
@ -91,8 +90,7 @@ static bool fix_win_pos_by_hint(Client *c, const XSizeHints *hint)
if(!c->owner && ((hint->flags & USPosition) || (hint->flags & PPosition)))
{
WIDGET_X(c->frame)=hint->x, WIDGET_Y(c->frame)=hint->y;
Rect r=get_win_rect_by_frame(c->frame);
WIDGET_X(c)=r.x, WIDGET_Y(c)=r.y;
set_client_rect_by_frame(c);
return true;
}
return false;
@ -129,8 +127,7 @@ static void fix_win_pos_by_workarea(WM *wm, Client *c)
WIDGET_Y(c->frame)=wy+wh-h-2*bw;
if(WIDGET_Y(c->frame) < wy) // 窗口在工作區上邊出界
WIDGET_Y(c->frame)=wy;
Rect r=get_win_rect_by_frame(c->frame);
WIDGET_X(c)=r.x, WIDGET_Y(c)=r.y;
set_client_rect_by_frame(c);
}
static void set_preview_layout(WM *wm)
@ -165,7 +162,7 @@ static void set_stack_layout(WM *wm)
{
if(is_on_cur_desktop(c->desktop_mask) && !is_iconic_client(c))
{
if(is_win_state_max(c) || c->win_state.fullscreen)
if(is_win_state_max(c->win_state) || c->win_state.fullscreen)
fix_win_rect_by_state(wm, c);
else
fix_win_rect(wm, c);
@ -357,7 +354,7 @@ void adjust_layout_ratio(WM *wm, XEvent *e, Func_arg arg)
request_layout_update(), ox=nx;
}
else
wm->event_handlers[ev.type](wm, &ev);
wm->handle_event(wm, &ev);
}while(!is_match_button_release(e, &ev));
XUngrabPointer(xinfo.display, CurrentTime);
}

View File

@ -9,12 +9,19 @@
* <http://www.gnu.org/licenses/>。
* ************************************************************************/
#include "mvresize.h"
//#include "mvresize.h"
#include "prop.h"
#include "minimax.h"
#include "client.h"
static void maximize_client(WM *wm, Client *c, Max_way way);
static void set_max_rect(WM *wm, Client *c, Max_way max_way);
static Rect get_vert_max_rect(const WM *wm, const Client *c);
static Rect get_horz_max_rect(const WM *wm, const Client *c);
static Rect get_top_max_rect(const WM *wm);
static Rect get_bottom_max_rect(const WM *wm);
static Rect get_left_max_rect(const WM *wm);
static Rect get_right_max_rect(const WM *wm);
static Client *get_icon_client_head(WM *wm);
static void set_fullscreen(WM *wm, Client *c);
@ -35,7 +42,7 @@ void max_restore(WM *wm, XEvent *e, Func_arg arg)
UNUSED(e), UNUSED(arg);
Client *c=CUR_FOC_CLI(wm);
if(is_win_state_max(c))
if(is_win_state_max(c->win_state))
restore_client(wm, c);
else
maximize_client(wm, c, FULL_MAX);
@ -49,10 +56,11 @@ void maximize(WM *wm, XEvent *e, Func_arg arg)
static void maximize_client(WM *wm, Client *c, Max_way max_way)
{
if(!is_win_state_max(c))
if(!is_win_state_max(c->win_state))
save_place_info_of_client(c);
set_max_rect(wm, c, max_way);
move_client(wm, c, NULL, get_dest_place_type_for_move(wm, c));
if(is_tiled_client(c))
move_client(wm, c, NULL, FLOAT_LAYER);
move_resize_client(c, NULL);
switch(max_way)
{
@ -69,34 +77,57 @@ static void maximize_client(WM *wm, Client *c, Max_way max_way)
static void set_max_rect(WM *wm, Client *c, Max_way max_way)
{
int left_x, top_y, max_w, max_h, mid_x, mid_y, half_w, half_h;
get_max_outline_rect(wm, &left_x, &top_y, &max_w, &max_h, &mid_x, &mid_y, &half_w, &half_h);
int x=WIDGET_X(c->frame), y=WIDGET_Y(c->frame), w=WIDGET_W(c->frame),
h=WIDGET_H(c->frame), bw=WIDGET_BORDER_W(c->frame);
bool vmax=(WIDGET_H(c->frame)+2*bw == max_h),
hmax=(WIDGET_W(c->frame)+2*bw == max_w), fmax=false;
int bw=WIDGET_BORDER_W(c->frame),
w=WIDGET_W(c->frame)+2*bw, h=WIDGET_H(c->frame)+2*bw;
Rect r=wm->workarea;
switch(max_way)
{
case VERT_MAX: if(hmax) fmax=true; else y=top_y, h=max_h; break;
case HORZ_MAX: if(vmax) fmax=true; else x=left_x, w=max_w; break;
case TOP_MAX: x=left_x, y=top_y, w=max_w, h=half_h; break;
case BOTTOM_MAX:x=left_x, y=mid_y, w=max_w, h=half_h; break;
case LEFT_MAX: x=left_x, y=top_y, w=half_w, h=max_h; break;
case RIGHT_MAX: x=mid_x, y=top_y, w=half_w, h=max_h; break;
case FULL_MAX: fmax=true; break;
default: return;
case VERT_MAX: if(w != r.h) r=get_vert_max_rect(wm, c); break;
case HORZ_MAX: if(h != r.w) r=get_horz_max_rect(wm, c); break;
case TOP_MAX: r=get_top_max_rect(wm); break;
case BOTTOM_MAX: r=get_bottom_max_rect(wm); break;
case LEFT_MAX: r=get_left_max_rect(wm); break;
case RIGHT_MAX: r=get_right_max_rect(wm); break;
case FULL_MAX: break;
default: return;
}
if(fmax)
x=left_x, y=top_y, w=max_w, h=max_h;
set_client_rect_by_outline(c, x, y, w, h);
set_client_rect_by_outline(c, r.x, r.y, r.w, r.h);
}
void get_max_outline_rect(WM *wm, int *left_x, int *top_y, int *max_w, int *max_h, int *mid_x, int *mid_y, int *half_w, int *half_h)
static Rect get_vert_max_rect(const WM *wm, const Client *c)
{
int wx=wm->workarea.x, wy=wm->workarea.y, ww=wm->workarea.w, wh=wm->workarea.h;
*left_x=wx, *top_y=wy, *max_w=ww, *max_h=wh,
*mid_x=*left_x+ww/2, *mid_y=*top_y+wh/2, *half_w=ww/2, *half_h=wh/2;
Rect r=get_widget_outline(WIDGET(c->frame)), w=wm->workarea;
return (Rect){r.x, w.y, r.w, w.h};
}
static Rect get_horz_max_rect(const WM *wm, const Client *c)
{
Rect r=get_widget_outline(WIDGET(c->frame)), w=wm->workarea;
return (Rect){w.x, r.y, w.w, r.h};
}
static Rect get_top_max_rect(const WM *wm)
{
Rect w=wm->workarea;
return (Rect){w.x, w.y, w.w, w.h/2};
}
static Rect get_bottom_max_rect(const WM *wm)
{
Rect w=wm->workarea;
return (Rect){w.x, w.y+w.h/2, w.w, w.h/2};
}
static Rect get_left_max_rect(const WM *wm)
{
Rect w=wm->workarea;
return (Rect){w.x, w.y, w.w/2, w.h};
}
static Rect get_right_max_rect(const WM *wm)
{
Rect w=wm->workarea;
return (Rect){w.x+w.w/2, w.y, w.w/2, w.h};
}
void restore_client(WM *wm, Client *c)
@ -120,15 +151,9 @@ void restore_client(WM *wm, Client *c)
update_net_wm_state(WIDGET_WIN(c), c->win_state);
}
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;
}
void fix_win_rect_by_state(WM *wm, Client *c)
{
if(is_win_state_max(c))
if(is_win_state_max(c->win_state))
{
Max_way way=FULL_MAX;
if(c->win_state.vmax) way=VERT_MAX;
@ -142,7 +167,10 @@ void fix_win_rect_by_state(WM *wm, Client *c)
set_max_rect(wm, c, way);
}
else if(c->win_state.fullscreen)
set_client_rect_by_win(c, 0, 0, xinfo.screen_width, xinfo.screen_height);
{
set_widget_rect(WIDGET(c), 0, 0, xinfo.screen_width, xinfo.screen_height);
set_frame_rect_by_client(c);
}
}
void iconify_client(WM *wm, Client *c)
@ -280,5 +308,6 @@ static void set_fullscreen(WM *wm, Client *c)
WIDGET_X(c)=WIDGET_Y(c)=0;
WIDGET_W(c)=xinfo.screen_width, WIDGET_H(c)=xinfo.screen_height;
move_client(wm, c, NULL, FULLSCREEN_LAYER);
c->win_state.fullscreen=1;
update_net_wm_state(WIDGET_WIN(c), c->win_state);
}

View File

@ -20,8 +20,6 @@ void max_restore(WM *wm, XEvent *e, Func_arg arg);
void maximize(WM *wm, XEvent *e, Func_arg arg);
void fix_win_rect_by_state(WM *wm, Client *c);
void restore_client(WM *wm, Client *c);
void get_max_outline_rect(WM *wm, int *left_x, int *top_y, int *max_w, int *max_h, int *mid_x, int *mid_y, int *half_w, int *half_h);
bool is_win_state_max(Client *c);
void fix_win_rect_by_state(WM *wm, Client *c);
void iconify_client(WM *wm, Client *c);
void deiconify_client(WM *wm, Client *c);

View File

@ -10,7 +10,6 @@
* ************************************************************************/
#include "icccm.h"
#include "minimax.h"
#include "mvresize.h"
static void key_move_resize_client(WM *wm, XEvent *e, Direction dir);
@ -35,7 +34,7 @@ void move_resize(WM *wm, XEvent *e, Func_arg arg)
pointer_move_resize_client(wm, e, arg.resize);
}
void key_move_resize_client(WM *wm, XEvent *e, Direction dir)
static void key_move_resize_client(WM *wm, XEvent *e, Direction dir)
{
if(DESKTOP(wm)->cur_layout == PREVIEW)
return;
@ -43,16 +42,15 @@ void key_move_resize_client(WM *wm, XEvent *e, Direction dir)
Client *c=CUR_FOC_CLI(wm);
bool is_move = (dir==UP || dir==DOWN || dir==LEFT || dir==RIGHT);
Delta_rect d=get_key_delta_rect(c, dir);
Place_type type=get_dest_place_type_for_move(wm, c);
if(c->place_type!=FLOAT_LAYER && type==FLOAT_LAYER)
move_client(wm, c, NULL, type);
if(is_tiled_client(c))
move_client(wm, c, NULL, FLOAT_LAYER);
if(get_move_resize_delta_rect(c, &d, is_move))
{
move_resize_client(c, &d);
update_hint_win_for_move_resize(c);
hide_hint_win_for_key_release(wm, e);
update_win_state_for_move_resize(wm, c);
update_net_wm_state_for_no_max(WIDGET_WIN(c), c->win_state);
}
}
@ -79,16 +77,10 @@ void hide_hint_win_for_key_release(WM *wm, XEvent *e)
break;
}
else
wm->event_handlers[ev.type](wm, &ev);
wm->handle_event(wm, &ev);
}
}
Place_type get_dest_place_type_for_move(WM *wm, Client *c)
{
return DESKTOP(wm)->cur_layout==TILE && is_tile_client(c) ?
FLOAT_LAYER : c->place_type;
}
static Delta_rect get_key_delta_rect(Client *c, Direction dir)
{
XSizeHints hint=get_size_hint(WIDGET_WIN(c));
@ -112,16 +104,7 @@ static Delta_rect get_key_delta_rect(Client *c, Direction dir)
return dr[dir];
}
void move_resize_client(Client *c, const Delta_rect *d)
{
if(d)
WIDGET_X(c)+=d->dx, WIDGET_Y(c)+=d->dy, WIDGET_W(c)+=d->dw, WIDGET_H(c)+=d->dh;
Rect fr=get_frame_rect_by_win(c->frame, WIDGET_X(c), WIDGET_Y(c), WIDGET_W(c), WIDGET_H(c));
move_resize_frame(c->frame, fr.x, fr.y, fr.w, fr.h);
XResizeWindow(xinfo.display, WIDGET_WIN(c), WIDGET_W(c), WIDGET_H(c));
}
void pointer_move_resize_client(WM *wm, XEvent *e, bool resize)
static void pointer_move_resize_client(WM *wm, XEvent *e, bool resize)
{
Layout layout=DESKTOP(wm)->cur_layout;
Move_info m={e->xbutton.x_root, e->xbutton.y_root, 0, 0};
@ -134,7 +117,6 @@ void pointer_move_resize_client(WM *wm, XEvent *e, bool resize)
XSizeHints hint=get_size_hint(WIDGET_WIN(c));
XEvent ev;
Place_type type=get_dest_place_type_for_move(wm, c);
if(act==MOVE || is_resizable(&hint))
{
do /* 因設置了獨享定位器且XMaskEvent會阻塞故應處理按、放按鈕之間的事件 */
@ -142,20 +124,19 @@ void pointer_move_resize_client(WM *wm, XEvent *e, bool resize)
XMaskEvent(xinfo.display, ROOT_EVENT_MASK|POINTER_MASK, &ev);
if(ev.type == MotionNotify)
{
static long n=1;
if(n++ == 1)
move_client(wm, c, NULL, type);
if(is_tiled_client(c))
move_client(wm, c, NULL, FLOAT_LAYER);
/* 因X事件是異步的故xmotion.x和ev.xmotion.y可能不是連續變化 */
m.nx=ev.xmotion.x, m.ny=ev.xmotion.y;
do_valid_pointer_move_resize(c, &m, act);
}
else
wm->event_handlers[ev.type](wm, &ev);
wm->handle_event(wm, &ev);
}while(!is_match_button_release(e, &ev));
}
XUngrabPointer(xinfo.display, CurrentTime);
XUnmapWindow(xinfo.display, xinfo.hint_win);
update_win_state_for_move_resize(wm, c);
update_net_wm_state_for_no_max(WIDGET_WIN(c), c->win_state);
}
static void do_valid_pointer_move_resize(Client *c, Move_info *m, Pointer_act act)
@ -216,7 +197,6 @@ static bool fix_delta_rect(Client *c, Delta_rect *d)
int dw=d->dw, dh=d->dh;
XSizeHints hint=get_size_hint(WIDGET_WIN(c));
//printf("w=%d, h=%d, dw=%d, dh=%d\n", WIDGET_W(c), WIDGET_H(c), dw, dh);
fix_dw_by_width_hint(WIDGET_W(c), &hint, &dw);
fix_dh_by_height_hint(WIDGET_W(c), &hint, &dh);
@ -228,7 +208,6 @@ static bool fix_delta_rect(Client *c, Delta_rect *d)
d->dx=-dw;
if(d->dy)
d->dy=-dh;
//printf("==> w=%d, h=%d, dw=%d, dh=%d\n", WIDGET_W(c), WIDGET_H(c), dw, dh);
return true;
}
@ -269,37 +248,6 @@ static void update_hint_win_for_move_resize(Client *c)
update_hint_win_for_info(None, str);
}
void update_win_state_for_move_resize(WM *wm, Client *c)
{
int x=WIDGET_X(c->frame), y=WIDGET_Y(c->frame),
w=WIDGET_W(c->frame), h=WIDGET_H(c->frame),
left_x, top_y, max_w, max_h, mid_x, mid_y, half_w, half_h;
bool update=false;
Net_wm_state *s=&c->win_state;
get_max_outline_rect(wm, &left_x, &top_y, &max_w, &max_h, &mid_x, &mid_y, &half_w, &half_h);
if(s->vmax && (y!=top_y || h!=max_h))
s->vmax=0, update=true;
if(s->hmax && (x!=left_x || w!=max_w))
s->hmax=0, update=true;
if( s->tmax && (x!=left_x || y!=top_y || w!=max_w || h!=half_h))
s->tmax=0, update=true;
if( s->bmax && (x!=left_x || y!=mid_y || w!=max_w || h!=half_h))
s->bmax=0, update=true;
if( s->lmax && (x!=left_x || y!=top_y || w!=half_w || h!=max_h))
s->lmax=0, update=true;
if( s->rmax && (x!=mid_x || y!=top_y || w!=half_w || h!=max_h))
s->rmax=0, update=true;
if(update)
update_net_wm_state(WIDGET_WIN(c), c->win_state);
}
Pointer_act get_resize_act(Client *c, const Move_info *m)
{ // 框架邊框寬度、可調整尺寸區域的寬度、高度
// 以及框架左、右橫坐標和上、下縱坐標
@ -349,18 +297,3 @@ void toggle_shade_client_mode(Client *c, bool shade)
move_resize_frame(c->frame, x, y, w, h+ch);
c->win_state.shaded=shade;
}
void set_client_rect_by_outline(Client *c, int x, int y, int w, int h)
{
int bw=WIDGET_BORDER_W(c->frame);
set_widget_rect(WIDGET(c->frame), x, y, w-2*bw, h-2*bw);
Rect r=get_win_rect_by_frame(c->frame);
set_widget_rect(WIDGET(c), r.x, r.y, r.w, r.h);
}
void set_client_rect_by_win(Client *c, int x, int y, int w, int h)
{
set_widget_rect(WIDGET(c), x, y, w, h);
Rect r=get_frame_rect_by_win(c->frame, x, y, w, h);
set_widget_rect(WIDGET(c->frame), r.x, r.y, r.w, r.h);
}

View File

@ -14,19 +14,9 @@
#include "gwm.h"
typedef struct /* 調整窗口尺寸的信息 */
{
int dx, dy, dw, dh; /* 分別爲窗口坐標和尺寸的變化量 */
} Delta_rect;
void move_resize(WM *wm, XEvent *e, Func_arg arg);
void move_resize_client(Client *c, const Delta_rect *d);
Place_type get_dest_place_type_for_move(WM *wm, Client *c);
void update_win_state_for_move_resize(WM *wm, Client *c);
Pointer_act get_resize_act(Client *c, const Move_info *m);
void toggle_shade_client(WM *wm, XEvent *e, Func_arg arg);
void toggle_shade_client_mode(Client *c, bool shade);
void set_client_rect_by_outline(Client *c, int x, int y, int w, int h);
void set_client_rect_by_win(Client *c, int x, int y, int w, int h);
#endif

View File

@ -11,7 +11,6 @@
#include "func.h"
#include "minimax.h"
#include "mvresize.h"
#include "prop.h"
#include "place.h"
@ -43,7 +42,7 @@ void pointer_change_place(WM *wm, XEvent *e, Func_arg arg)
move_client(wm, from, NULL, TILE_LAYER_MAIN);
else if(to)
move_client(wm, from, to, ANY_PLACE);
update_win_state_for_move_resize(wm, from);
update_net_wm_state_for_no_max(WIDGET_WIN(from), from->win_state);
}
void change_place(WM *wm, XEvent *e, Func_arg arg)
@ -51,7 +50,7 @@ void change_place(WM *wm, XEvent *e, Func_arg arg)
UNUSED(e);
Client *c=CUR_FOC_CLI(wm);
move_client(wm, c, NULL, arg.place_type);
update_win_state_for_move_resize(wm, c);
update_net_wm_state_for_no_max(WIDGET_WIN(c), c->win_state);
}
void pointer_swap_clients(WM *wm, XEvent *e, Func_arg arg)

View File

@ -145,13 +145,13 @@ void hide_widget(const Widget *widget)
void resize_widget(Widget *widget, int w, int h)
{
widget->w=w, widget->h=h;;
widget->w=w, widget->h=h;
XResizeWindow(xinfo.display, widget->win, w, h);
}
void move_resize_widget(Widget *widget, int x, int y, int w, int h)
{
widget->x=x, widget->y=y, widget->w=w, widget->h=h;
set_widget_rect(widget, x, y, w, h);
XMoveResizeWindow(xinfo.display, widget->win, x, y, w, h);
}
@ -170,6 +170,12 @@ void set_widget_rect(Widget *widget, int x, int y, int w, int h)
widget->x=x, widget->y=y, widget->w=w, widget->h=h;
}
Rect get_widget_outline(const Widget *widget)
{
int bw=widget->border_w;
return (Rect){widget->x, widget->y, widget->w+2*bw, widget->h+2*bw};
}
Window create_widget_win(Window parent, int x, int y, int w, int h, int border_w, unsigned long border_pixel, unsigned long bg_pixel)
{
XSetWindowAttributes attr;

View File

@ -78,6 +78,8 @@ struct _widget_tag
void (*update_fg)(const Widget *widget);
};
typedef struct rectangle_tag Rect;
#define WIDGET_EVENT_MASK (ExposureMask)
#define TITLE_BUTTON_N (TITLE_BUTTON_END-TITLE_BUTTON_BEGIN+1)
#define TASKBAR_BUTTON_N (TASKBAR_BUTTON_END-TASKBAR_BUTTON_BEGIN+1)
@ -115,6 +117,7 @@ void move_resize_widget(Widget *widget, int x, int y, int w, int h);
void update_widget_bg(const Widget *widget);
void update_widget_fg(const Widget *widget);
void set_widget_rect(Widget *widget, int x, int y, int w, int h);
Rect get_widget_outline(const Widget *widget);
Window create_widget_win(Window parent, int x, int y, int w, int h, int border_w, unsigned long border_pixel, unsigned long bg_pixel);
void update_hint_win_for_info(const Widget *widget, const char *info);
void set_xic(Window win, XIC *ic);