Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/c/61.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
X-DWM——帮助我修复C源代码中的一个bug_C_X Dwm - Fatal编程技术网

X-DWM——帮助我修复C源代码中的一个bug

X-DWM——帮助我修复C源代码中的一个bug,c,x-dwm,C,X Dwm,我正在使用(6.2)窗口管理器,我发现了一个我很想解决的bug 窗口管理器在放置窗口的位置使用“主区域”和“堆栈区域”: 可以使用ALT+i将“堆栈区域”顶部的窗口移动到“主区域”底部。也可以使用ALT+d将窗口从“主区域”的底部移回“堆栈区域”的顶部 现在,在这种情况下,如果我使用ALT+I,布局会改变,在组合键之后,“主区域”中有两个窗口: 我再重复一遍,现在“主区域”中有三个窗口: 我再重复一遍,现在“主区域”中有三个窗口,宽度为100%: 如果此时我决定将窗口从“主区域”返回到“

我正在使用(6.2)窗口管理器,我发现了一个我很想解决的bug

窗口管理器在放置窗口的位置使用“主区域”和“堆栈区域”:

可以使用ALT+i将“堆栈区域”顶部的窗口移动到“主区域”底部。也可以使用ALT+d将窗口从“主区域”的底部移回“堆栈区域”的顶部

现在,在这种情况下,如果我使用ALT+I,布局会改变,在组合键之后,“主区域”中有两个窗口:

我再重复一遍,现在“主区域”中有三个窗口:

我再重复一遍,现在“主区域”中有三个窗口,宽度为100%:

如果此时我决定将窗口从“主区域”返回到“堆栈区域”,我将开始按ALT+d,windows将立即返回到“堆栈区域”。这很好用

但是我故意犯了一个错误,而是再次按ALT+I,例如三次。看起来什么都没发生

但是现在,如果我尝试将窗口从“主区域”返回到“堆栈区域”,我首先需要再按ALT+d三次,然后什么也不会发生!最后,当我第四次按ALT+d时,窗口管理器会将第一个窗口从“主区域”的底部返回到“堆栈区域”的顶部

所以这不是经过深思熟虑的,应该被认为是一个bug


源代码中一定有某种计数器,按ALT+i再增加三倍,但在所有窗口都已位于“主区域”后,计数器不应增加


config.def.h
源文件()中,有一部分代码用于分配密钥。在这里我可以看到,当用户按下ALT+I时,调用函数
incnmaster()
,并传递一个参数
。I=+1
(我不理解这个参数)

Key
dwm.c
源文件()中的一个结构:

函数
incnmaster()
dwm.c
源文件()中定义:

其中
arg
是指向
arg
arg*
)的指针,它是一个联合体(我不太明白如何处理参数
。I=+1
):

selmon
是一种结构
Monitor

struct Monitor {
    char ltsymbol[16];
    float mfact;
    int nmaster;
    int num;
    int by;               /* bar geometry */
    int mx, my, mw, mh;   /* screen size */
    int wx, wy, ww, wh;   /* window area  */
    unsigned int seltags;
    unsigned int sellt;
    unsigned int tagset[2];
    int showbar;
    int topbar;
    Client *clients;
    Client *sel;
    Client *stack;
    Monitor *next;
    Window barwin;
    const Layout *lt[2];
};
struct Monitor {
    char ltsymbol[16];
    float mfact;
    int nmaster;
    int nclients;
    int num;
    int by;               /* bar geometry */
    int mx, my, mw, mh;   /* screen size */
    int wx, wy, ww, wh;   /* window area  */
    unsigned int seltags;
    unsigned int sellt;
    unsigned int tagset[2];
    int showbar;
    int topbar;
    Client *clients;
    Client *sel;
    Client *stack;
    Monitor *next;
    Window barwin;
    const Layout *lt[2];
};
MAX
在单独的源文件
util.h
()中定义为:

函数
arrange()
的定义如下:

 void
 arrange(Monitor *m)
 {
    if (m)
        showhide(m->stack);
    else for (m = mons; m; m = m->next)
        showhide(m->stack);
    if (m) {
        arrangemon(m);
        restack(m);
    } else for (m = mons; m; m = m->next)
        arrangemon(m);
}
我想我不必再挖了



现在我认为我需要在C代码中实现某种类型的
if
语句,以防止
selmon->nmaster
增加太多,但我有点困惑。有人能帮忙吗?

在我自己弄明白这个问题之前,没有人回答。问题是,无吸团队从未实现任何类型的机制来计算打开的窗口数(他们称之为客户机)。这就是为什么我添加了
int-nclients结构的成员
监视器

struct Monitor {
    char ltsymbol[16];
    float mfact;
    int nmaster;
    int num;
    int by;               /* bar geometry */
    int mx, my, mw, mh;   /* screen size */
    int wx, wy, ww, wh;   /* window area  */
    unsigned int seltags;
    unsigned int sellt;
    unsigned int tagset[2];
    int showbar;
    int topbar;
    Client *clients;
    Client *sel;
    Client *stack;
    Monitor *next;
    Window barwin;
    const Layout *lt[2];
};
struct Monitor {
    char ltsymbol[16];
    float mfact;
    int nmaster;
    int nclients;
    int num;
    int by;               /* bar geometry */
    int mx, my, mw, mh;   /* screen size */
    int wx, wy, ww, wh;   /* window area  */
    unsigned int seltags;
    unsigned int sellt;
    unsigned int tagset[2];
    int showbar;
    int topbar;
    Client *clients;
    Client *sel;
    Client *stack;
    Monitor *next;
    Window barwin;
    const Layout *lt[2];
};
然后我通过添加
m->nclients=0,确保在启动时将其初始化为
0
createmon()
函数中,我猜该函数是在开头运行的:

Monitor *
createmon(void)
{
    Monitor *m;

    m = ecalloc(1, sizeof(Monitor));
    m->tagset[0] = m->tagset[1] = 1;
    m->mfact = mfact;
    m->nmaster = nmaster;
    m->nclients = 0;
    m->showbar = showbar;
    m->topbar = topbar;
    m->gappx = gappx;
    m->lt[0] = &layouts[0];
    m->lt[1] = &layouts[1 % LENGTH(layouts)];
    strncpy(m->ltsymbol, layouts[0].symbol, sizeof m->ltsymbol);
    return m;
}
然后,我确保当新窗口出现时,我的计数器
nclients
会增加。我添加了
++selmon->nclients
排列(selmon)
(在关闭其中一个客户端后,能够立即将客户端移动到stack/master ime)函数开头的
spawn()
语句:

void
spawn(const Arg *arg)
{
    ++selmon->nclients;
    arrange(selmon);
    if (arg->v == dmenucmd)
        dmenumon[0] = '0' + selmon->num;
    if (fork() == 0) {
        if (dpy)
            close(ConnectionNumber(dpy));
        setsid();
        execvp(((char **)arg->v)[0], (char **)arg->v);
        fprintf(stderr, "dwm: execvp %s", ((char **)arg->v)[0]);
        perror(" failed");
        exit(EXIT_SUCCESS);
    }
}
void
killclient(const Arg *arg)
{
    --selmon->nclients;
    arrange(selmon);
    if (!selmon->sel)
        return;
    if (!sendevent(selmon->sel->win, wmatom[WMDelete], NoEventMask, wmatom[WMDelete], CurrentTime, 0 , 0, 0)) {
        XGrabServer(dpy);
        XSetErrorHandler(xerrordummy);
        XSetCloseDownMode(dpy, DestroyAll);
        XKillClient(dpy, selmon->sel->win);
        XSync(dpy, False);
        XSetErrorHandler(xerror);
        XUngrabServer(dpy);
    }
}
当车窗关闭时,计数器应减小。这就是为什么我添加了
--selmon->nclients
排列(selmon)
(在关闭其中一个客户端后,能够立即将客户端移动到stack/master i中)位于
killclient()函数顶部:

void
spawn(const Arg *arg)
{
    ++selmon->nclients;
    arrange(selmon);
    if (arg->v == dmenucmd)
        dmenumon[0] = '0' + selmon->num;
    if (fork() == 0) {
        if (dpy)
            close(ConnectionNumber(dpy));
        setsid();
        execvp(((char **)arg->v)[0], (char **)arg->v);
        fprintf(stderr, "dwm: execvp %s", ((char **)arg->v)[0]);
        perror(" failed");
        exit(EXIT_SUCCESS);
    }
}
void
killclient(const Arg *arg)
{
    --selmon->nclients;
    arrange(selmon);
    if (!selmon->sel)
        return;
    if (!sendevent(selmon->sel->win, wmatom[WMDelete], NoEventMask, wmatom[WMDelete], CurrentTime, 0 , 0, 0)) {
        XGrabServer(dpy);
        XSetErrorHandler(xerrordummy);
        XSetCloseDownMode(dpy, DestroyAll);
        XKillClient(dpy, selmon->sel->win);
        XSync(dpy, False);
        XSetErrorHandler(xerror);
        XUngrabServer(dpy);
    }
}
现在计数器已经设置好,我可以用它重写
incnmaster()
函数,如下所示:

void
incnmaster(const Arg *arg)
{
    if((arg->i > 0) && (selmon->nmaster < selmon->nclients)){
        ++selmon->nmaster;
    }
    if((arg->i < 0) && (selmon->nmaster > 0)){
        --selmon->nmaster;
    }
    arrange(selmon);

}
void
incnmaster(常量参数*Arg)
{
if((arg->i>0)和&(selmon->nmasternclients)){
++selmon->nmaster;
}
if((arg->i<0)和&(selmon->nmaster>0)){
--selmon->nmaster;
}
安排(塞尔蒙);
}
注意。我的DWM有点补丁,所以有些行可能有点问题 与你的不同,但只要坚持同样的理念 我能解决这个问题

这个解决方案部分有效。只有当我:

A.使用
dmenu
dmenu
启动时可以(a)打开客户端或(b)不执行任何操作。如果(a)一切正常,但如果(b)
nmaster
n客户端再次失去同步

因此,例如,如果我执行场景(b)一次,并无数次使用CTRL+I,我将不得不使用CTRL+d一次,什么也不会发生,但如果我再次使用它,一个窗口将从主窗口移动到堆栈区域

B.从终端运行任何类型的窗口应用程序 看起来DWM无法跟踪从终端运行的窗口并以错误的方式处理它们。。。在这种情况下,
nmaster
nclients
也会变得不同步


有人知道在打开任何类型的窗口时,除了执行
spawn
之外,是否还有其他功能


这还没有解决 当它是一个链表时,为什么你要持有客户数量?您无法按需获取客户数量。类似的代码也可以找到。如果您真的必须自己计算(出于性能原因),我会查看dwm修改客户机列表的任何地方,并将该修改投影到计数器

结构客户机包含指向“下一个”客户机的指针,实现可能取决于何时需要使用multihead su
void
incnmaster(const Arg *arg)
{
    if((arg->i > 0) && (selmon->nmaster < selmon->nclients)){
        ++selmon->nmaster;
    }
    if((arg->i < 0) && (selmon->nmaster > 0)){
        --selmon->nmaster;
    }
    arrange(selmon);

}