XCB: mouse events handling and background color
authorRémi Denis-Courmont <rdenis@simphalempin.com>
Sun, 25 Jan 2009 11:11:27 +0000 (13:11 +0200)
committerRémi Denis-Courmont <rdenis@simphalempin.com>
Sun, 25 Jan 2009 11:11:27 +0000 (13:11 +0200)
modules/video_output/Modules.am
modules/video_output/xcb/events.c [new file with mode: 0644]
modules/video_output/xcb/xcb.c
modules/video_output/xcb/xcb_vlc.h [new file with mode: 0644]

index b3be41c..5ca9823 100644 (file)
@@ -26,7 +26,10 @@ XCB_SHM_LIBS = -lxcb-shm
 XCB_AUX_LIBS = -lxcb-aux
 XCB_IMAGE_LIBS = -lxcb-image
 
-libxcb_plugin_la_SOURCES = xcb/xcb.c
+libxcb_plugin_la_SOURCES = \
+       xcb/xcb_vlc.h \
+       xcb/xcb.c \
+       xcb/events.c
 libxcb_plugin_la_CFLAGS = $(AM_CFLAGS) \
        $(XCB_CFLAGS) $(XCB_SHM) \
        $(XCB_AUX_CFLAGS) $(XCB_IMAGE_CFLAGS)
diff --git a/modules/video_output/xcb/events.c b/modules/video_output/xcb/events.c
new file mode 100644 (file)
index 0000000..89c6273
--- /dev/null
@@ -0,0 +1,110 @@
+/**
+ * @file events.c
+ * @brief X C Bindings VLC video output events handling
+ */
+/*****************************************************************************
+ * Copyright © 2009 Rémi Denis-Courmont
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2.0
+ * of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ ****************************************************************************/
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <inttypes.h>
+
+#include <xcb/xcb.h>
+
+#include <vlc_common.h>
+#include <vlc_vout.h>
+
+#include "xcb_vlc.h"
+
+/* NOTE: we assume no other thread will be _setting_ our video output events
+ * variables. Afterall, only this plugin is supposed to know when these occur.
+  * Otherwise, we'd var_OrInteger() and var_NandInteger() functions...
+ */
+
+static void HandleButtonPress (vout_thread_t *vout,
+                               xcb_button_press_event_t *ev)
+{
+    unsigned buttons = var_GetInteger (vout, "mouse-button-down");
+    buttons |= (1 << (ev->detail - 1));
+    var_SetInteger (vout, "mouse-button-down", buttons);
+}
+
+static void HandleButtonRelease (vout_thread_t *vout,
+                                 xcb_button_release_event_t *ev)
+{
+    unsigned buttons = var_GetInteger (vout, "mouse-button-down");
+    buttons &= ~(1 << (ev->detail - 1));
+    var_SetInteger (vout, "mouse-button-down", buttons);
+
+    if (ev->detail == 1) /* left mouse button */
+        var_SetBool (vout, "mouse-clicked", true);
+}
+
+static void HandleMotionNotify (vout_thread_t *vout,
+                                xcb_motion_notify_event_t *ev)
+{
+    unsigned x, y, width, height;
+    int v;
+
+    vout_PlacePicture (vout, vout->output.i_width, vout->output.i_height,
+                       &x, &y, &width, &height);
+    v = vout->fmt_in.i_x_offset
+        + ((ev->event_x - x) * vout->fmt_in.i_visible_width / width);
+    if (v < 0)
+        v = 0; /* to the left of the picture */
+    else if ((unsigned)v > vout->fmt_in.i_width)
+        v = vout->fmt_in.i_width; /* to the right of the picture */
+    var_SetInteger (vout, "mouse-x", v);
+
+    v = vout->fmt_in.i_y_offset
+        + ((ev->event_y - y) * vout->fmt_in.i_visible_height / height);
+    if (v < 0)
+        v = 0; /* above the picture */
+    else if ((unsigned)v > vout->fmt_in.i_height)
+        v = vout->fmt_in.i_height; /* below the picture */
+    var_SetInteger (vout, "mouse-y", v);
+}
+
+/**
+ * Process an X11 event.
+ */
+int ProcessEvent (vout_thread_t *vout, xcb_generic_event_t *ev)
+{
+    switch (ev->response_type & 0x7f)
+    {
+        case XCB_BUTTON_PRESS:
+            HandleButtonPress (vout, (xcb_button_press_event_t *)ev);
+            break;
+
+        case XCB_BUTTON_RELEASE:
+            HandleButtonRelease (vout, (xcb_button_release_event_t *)ev);
+            break;
+
+        case XCB_MOTION_NOTIFY:
+            HandleMotionNotify (vout, (xcb_motion_notify_event_t *)ev);
+            break;
+
+        default:
+            msg_Dbg (vout, "unhandled event %02x", (unsigned)ev->response_type);
+    }
+
+    free (ev);
+    return VLC_SUCCESS;
+}
index f9a02cf..3523602 100644 (file)
@@ -41,6 +41,8 @@
 #include <vlc_vout.h>
 #include <vlc_window.h>
 
+#include "xcb_vlc.h"
+
 #define DISPLAY_TEXT N_("X11 display")
 #define DISPLAY_LONGTEXT N_( \
     "X11 hardware display to use. By default VLC will " \
@@ -88,8 +90,7 @@ static void Deinit (vout_thread_t *);
 static void Display (vout_thread_t *, picture_t *);
 static int Manage (vout_thread_t *);
 
-static int CheckError (vout_thread_t *vout, const char *str,
-                       xcb_void_cookie_t ck)
+int CheckError (vout_thread_t *vout, const char *str, xcb_void_cookie_t ck)
 {
     xcb_generic_error_t *err;
 
@@ -402,16 +403,24 @@ static int Init (vout_thread_t *vout)
     /* FIXME: I don't get the subtlety between output and fmt_out here */
 
     /* Create window */
+    const uint32_t mask = XCB_CW_BACK_PIXEL | XCB_CW_EVENT_MASK;
+    uint32_t values[2] = {
+        /* XCB_CW_BACK_PIXEL */
+        screen->black_pixel,
+        /* XCB_CW_EVENT_MASK */
+        XCB_EVENT_MASK_BUTTON_PRESS | XCB_EVENT_MASK_BUTTON_RELEASE |
+        XCB_EVENT_MASK_POINTER_MOTION,
+    };
     xcb_void_cookie_t c;
     xcb_window_t window = xcb_generate_id (p_sys->conn);
 
-    p_sys->window = window;
     c = xcb_create_window_checked (p_sys->conn, screen->root_depth, window,
                                    p_sys->parent, x, y, width, height, 0,
                                    XCB_WINDOW_CLASS_INPUT_OUTPUT,
-                                   screen->root_visual, 0, NULL);
+                                   screen->root_visual, mask, values);
     if (CheckError (vout, "cannot create X11 window", c))
         goto error;
+    p_sys->window = window;
     msg_Dbg (vout, "using X11 window %08"PRIx32, p_sys->window);
     xcb_map_window (p_sys->conn, window);
 
@@ -498,14 +507,7 @@ static int Manage (vout_thread_t *vout)
     xcb_generic_event_t *ev;
 
     while ((ev = xcb_poll_for_event (p_sys->conn)) != NULL)
-    {
-        switch (ev->response_type & ~0x80)
-        {
-        default:
-            msg_Dbg (vout, "unhandled event %02x", (unsigned)ev->response_type);
-        }
-        free (ev);
-    }
+        ProcessEvent (vout, ev);
 
     if (xcb_connection_has_error (p_sys->conn))
     {
diff --git a/modules/video_output/xcb/xcb_vlc.h b/modules/video_output/xcb/xcb_vlc.h
new file mode 100644 (file)
index 0000000..e93f2ee
--- /dev/null
@@ -0,0 +1,24 @@
+/**
+ * @file xcb_vlc.h
+ * @brief X C Bindings VLC module common header
+ */
+/*****************************************************************************
+ * Copyright © 2009 Rémi Denis-Courmont
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2.0
+ * of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ ****************************************************************************/
+
+int CheckError (vout_thread_t *, const char *str, xcb_void_cookie_t);
+int ProcessEvent (vout_thread_t *, xcb_generic_event_t *);