Score:1

การเขียนโปรแกรม C: ตรวจจับการเคลื่อนไหวของตัวชี้เมาส์

ธง pt

ฉันกำลังทำงานในโครงการที่ฉันต้องตั้งค่าสถานะเฉพาะเมื่อตัวชี้เมาส์ไม่ได้ขยับเป็นระยะเวลาหนึ่ง (เช่น: 30 วินาที): หากเมาส์ไม่ได้ใช้งานเป็นเวลา 30 วินาที ให้ตั้งค่า no_movement (no_movement=จริง;).

จนถึงตอนนี้ ฉันรู้ว่าเซิร์ฟเวอร์ X window เป็นแบ็กเอนด์สำหรับสภาพแวดล้อมเดสก์ท็อปจำนวนมาก และฉันรู้ว่ามีเอกสารประกอบที่ครอบคลุม x.org และ tronche.com (ได้ความมาว่ามีกิจกรรมสำหรับพอยน์เตอร์เรียกว่า แจ้งเตือนการเคลื่อนไหว).

โดยใช้ ฉลาดแสดง xserver-xorg | รุ่น grep ฉันพบว่าเวอร์ชัน Xserver ที่ติดตั้งในระบบของฉันคือ 1:7.7+22ubuntu1 (บน Ubuntu 21.04)

วิธีที่แนะนำในการรับข้อเสนอแนะการเคลื่อนไหวของตัวชี้เมาส์คืออะไร

ขอบคุณสำหรับเวลาของคุณตอบสนองฉัน

HuHa avatar
es flag
ทำไมฉันได้กลิ่นความชั่วร้ายบางอย่าง "คนทำงานที่บ้านของฉันทำงานหรือเปล่า" ซอฟต์แวร์ที่นี่?
Shobeira avatar
pt flag
ฉันกำลังพยายามจับเวลาของฉันจริงๆ ฉันจำเป็นต้องรู้ว่าฉันทำงานในโครงการมากเพียงใด เนื่องจากเรากำลังเผชิญกับการล็อกดาวน์ครั้งที่ 5 และยังคงทำงานจากที่บ้าน
Score:0
ธง in

X11 ได้รับการบันทึกไว้ค่อนข้างดีสำหรับ 'มาสก์เหตุการณ์'

https://tronche.com/gui/x/xlib/events/mask.html

หรือมี XQueryPointer เสมอ)..

// ลองใช้โปรแกรม C นี้เป็นพื้นฐานของสิ่งที่ต้องการทำ..

    #รวม <stdio.h>
#รวม <assert.h>
#รวม <X11/Xlib.h>
#รวม <X11/extensions/XInput2.h>

int หลัก (int argc, ถ่าน ** argv)
{
    จอแสดงผล *จอแสดงผล;
    หน้าต่าง root_window;

    /* Initialize (FIXME: ไม่มีการตรวจสอบข้อผิดพลาด) */
    จอแสดงผล = XOpenDisplay(0);
    root_window = XRootWindow (แสดง, 0);

    /* ตรวจสอบ XInput */
    int xi_opcode, เหตุการณ์, ข้อผิดพลาด;
    ถ้า (!XQueryExtension(แสดงผล, "XInputExtension", &xi_opcode, &event, &error)) {
        fprintf(stderr, "ข้อผิดพลาด: ไม่รองรับส่วนขยาย XInput!\n");
        กลับ 1;
    }

    /* ตรวจสอบ XInput 2.0 */
    int หลัก = 2;
    int เล็กน้อย = 0;
    int retval = XIQueryVersion(แสดง &หลัก &รอง);
    ถ้า (retval != สำเร็จ) {
        fprintf(stderr, "ข้อผิดพลาด: ไม่รองรับ XInput 2.0 (X11 โบราณ?)\n");
        กลับ 1;
    }

    /*
     * ตั้งหน้ากากเพื่อรับเหตุการณ์ XI_RawMotion เพราะมันดิบ
     * ไม่รวมเหตุการณ์ XWarpPointer() คุณสามารถใช้ XI_Motion
     * แทน.
     */
    char mask_bytes ที่ไม่ได้ลงชื่อ [(XI_LASTEVENT + 7) / 8] = {0}; /* ต้องมีค่าเป็นศูนย์! */
    XISetMask (mask_bytes, XI_RawMotion);

    /* ตั้งค่าหน้ากากเพื่อรับเหตุการณ์จากอุปกรณ์หลักทั้งหมด */
    XIEventMask evmasks[1];
    /* คุณสามารถใช้ XIAllDevices สำหรับ XWarpPointer() */
    evmasks[0].deviceid = XIAllMasterDevices;
    evmasks[0].mask_len = sizeof(mask_bytes);
    evmasks[0].mask = mask_bytes;
    XISelectEvents (แสดง, root_window, evmasks, 1);

    XEvent xเหตุการณ์;
    ในขณะที่ (1) {
        XNextEvent(แสดง, &xevent);

        ถ้า (xevent.xcookie.type != GenericEvent || xevent.xcookie.extension != xi_opcode) {
            /* ไม่ใช่เหตุการณ์ XInput */
            ดำเนินต่อ;
        }
        XGetEventData(ดิสเพลย์, &xevent.xcookie);
        ถ้า (xevent.xcookie.evtype != XI_RawMotion) {
            /*
             * ไม่ใช่เหตุการณ์ XI_RawMotion (คุณอาจต้องการตรวจจับ
             * XI_Motion เช่นกัน ดูความคิดเห็นด้านบน).
             */
            XFreeEventData(ดิสเพลย์, &xevent.xcookie);
            ดำเนินต่อ;
        }
        XFreeEventData(ดิสเพลย์, &xevent.xcookie);

        หน้าต่าง root_return, child_return;
        int root_x_return, root_y_return;
        int win_x_return, win_y_return;
        int mask_return ที่ไม่ได้ลงนาม;
        /*
         * พวกเราต้องการ:
         * child_return - หน้าต่างที่ใช้งานอยู่ใต้เคอร์เซอร์
         * win_{x,y}_return - ตัวชี้ประสานงานกับหน้าต่างรูท
         */
        int retval = XQueryPointer(จอแสดงผล, root_window, &root_return, &child_return,
                                   &root_x_return, &root_y_return,
                                   &win_x_return, &win_y_return,
                                   &mask_return);
        ถ้า (!retval) {
            /* ตัวชี้ไม่อยู่ในหน้าจอเดียวกัน ไม่ต้องสนใจ */
            ดำเนินต่อ;
        }

        /* เราใช้หน้าต่างรูทเป็นข้อมูลอ้างอิง ดังนั้นทั้งสองควรจะเหมือนกัน */
        ยืนยัน (root_x_return == win_x_return);
        ยืนยัน (root_y_return == win_y_return);

        printf("รูท: x %d y %d\n", root_x_return, root_y_return);

        ถ้า (child_return) {
            int local_x, local_y;
            XTranslateCoordinates (แสดง, root_window, child_return,
                                  root_x_return, root_y_return,
                                  &local_x, &local_y, &child_return);
            printf("local: x %d y %d\n\n", local_x, local_y);
        }
    }

    XCloseDisplay(แสดงผล);

    กลับ 0;
}
Shobeira avatar
pt flag
ขอบคุณคำตอบของคุณ ฉันมาถูกทางแล้วใช่ไหม X window เป็นแนวทางที่ดีหรือไม่? ขณะที่ฉันกำลังดูมาสก์เหตุการณ์ ฉันพบว่า MotionNotify เป็นมาสก์ที่เหมาะสมที่สุด เนื่องจากฉันต้องการการคืนค่าบูลีนสำหรับปัญหา สิ่งที่ฉันคิดว่ามีโครงสร้าง X ที่เกี่ยวข้อง เริ่มต้นมัน แล้วประเมินมันกับหน้ากากเหตุการณ์ ฉันต้องการการเคลื่อนไหว/no_movement..
in flag
ไม่มีปัญหา ฉันคิดว่าถ้าคุณต้องการตรวจจับการเคลื่อนไหวนั่นค่อนข้างง่าย... เพียงตรวจสอบ X\Y ของตำแหน่งเมาส์และหากมีการเปลี่ยนแปลง แสดงว่าคุณเคลื่อนไหวแล้ว.. ขั้นตอนแรกคือการรับเหตุการณ์ตัวชี้ตั้งแต่แรก ..

โพสต์คำตอบ

คนส่วนใหญ่ไม่เข้าใจว่าการถามคำถามมากมายจะปลดล็อกการเรียนรู้และปรับปรุงความสัมพันธ์ระหว่างบุคคล ตัวอย่างเช่น ในการศึกษาของ Alison แม้ว่าผู้คนจะจำได้อย่างแม่นยำว่ามีคำถามกี่ข้อที่ถูกถามในการสนทนา แต่พวกเขาไม่เข้าใจความเชื่อมโยงระหว่างคำถามและความชอบ จากการศึกษาทั้ง 4 เรื่องที่ผู้เข้าร่วมมีส่วนร่วมในการสนทนาด้วยตนเองหรืออ่านบันทึกการสนทนาของผู้อื่น ผู้คนมักไม่ตระหนักว่าการถามคำถามจะมีอิทธิพลหรือมีอิทธิพลต่อระดับมิตรภาพระหว่างผู้สนทนา