]> git.sesse.net Git - vlc/commitdiff
XCB: resize support
authorRémi Denis-Courmont <remi@remlab.net>
Thu, 9 Apr 2009 14:54:41 +0000 (17:54 +0300)
committerRémi Denis-Courmont <remi@remlab.net>
Thu, 9 Apr 2009 14:59:20 +0000 (17:59 +0300)
Note that the video output core seems to call pf_end while some pictures
are still in use upstream. That will crash. IMHO, this is a libvlc bug,
as the vout plugin cannot know when to release the picture or reallocate
those pictures.

modules/video_output/xcb/events.c
modules/video_output/xcb/xcb.c
modules/video_output/xcb/xcb_vlc.h

index 908f8116c5ca9f01656a23aa28b06b30df7ca000..bffe407df0610108493e05832b65eadcf3cd3fd3 100644 (file)
@@ -90,10 +90,32 @@ static void HandleMotionNotify (vout_thread_t *vout,
     var_SetInteger (vout, "mouse-y", v);
 }
 
+static void
+HandleParentStructure (vout_thread_t *vout, xcb_connection_t *conn,
+                       xcb_window_t xid, xcb_configure_notify_event_t *ev)
+{
+    unsigned width, height, x, y;
+
+    vout_PlacePicture (vout, ev->width, ev->height, &x, &y, &width, &height);
+    if (width != vout->fmt_out.i_visible_width
+     || height != vout->fmt_out.i_visible_height)
+    {
+        vout->i_changes |= VOUT_SIZE_CHANGE;
+        return; /* vout will be reinitialized */
+    }
+
+    /* Move the picture within the window */
+    const uint32_t values[] = { x, y, };
+    xcb_configure_window (conn, xid,
+                          XCB_CONFIG_WINDOW_X | XCB_CONFIG_WINDOW_Y,
+                          values);
+}
+
 /**
  * Process an X11 event.
  */
-int ProcessEvent (vout_thread_t *vout, xcb_generic_event_t *ev)
+int ProcessEvent (vout_thread_t *vout, xcb_connection_t *conn,
+                  xcb_window_t window, xcb_generic_event_t *ev)
 {
     switch (ev->response_type & 0x7f)
     {
@@ -109,6 +131,16 @@ int ProcessEvent (vout_thread_t *vout, xcb_generic_event_t *ev)
             HandleMotionNotify (vout, (xcb_motion_notify_event_t *)ev);
             break;
 
+        case XCB_CONFIGURE_NOTIFY:
+        {
+            xcb_configure_notify_event_t *cn =
+                (xcb_configure_notify_event_t *)ev;
+
+            assert (cn->window != window)
+            HandleParentStructure (vout, conn, window, cn);
+            break;
+        }
+
         default:
             msg_Dbg (vout, "unhandled event %"PRIu8, ev->response_type);
     }
index 0f1eafeb3b9da8b5e75ef203f0b38d7a2afe79e6..e3dd91aa223e9bee03f6ceb6479fbef59a3b127e 100644 (file)
@@ -233,6 +233,16 @@ static int Open (vlc_object_t *obj)
         }
     }
 
+    /* Get window */
+    /* FIXME: WTH to put as initial width/height values??? */
+    p_sys->embed = vout_RequestXWindow (vout, &(int){ 0 }, &(int){ 0 },
+                                        &(unsigned){ 0 }, &(unsigned){ 0 });
+    if (p_sys->embed == NULL)
+    {
+        msg_Err (vout, "parent window not available");
+        goto error;
+    }
+
     vout->pf_init = Init;
     vout->pf_end = Deinit;
     vout->pf_render = Render;
@@ -254,7 +264,8 @@ static void Close (vlc_object_t *obj)
     vout_thread_t *vout = (vout_thread_t *)obj;
     vout_sys_t *p_sys = vout->p_sys;
 
-    assert (p_sys->embed == NULL);
+    if (p_sys->embed)
+        vout_ReleaseWindow (p_sys->embed);
     /* colormap is garbage-ollected by X (?) */
     if (p_sys->conn)
         xcb_disconnect (p_sys->conn);
@@ -403,27 +414,33 @@ static int Init (vout_thread_t *vout)
     const xcb_screen_t *screen = p_sys->screen;
     unsigned x, y, width, height;
 
-    /* Determine parent window */
+    /* Determine parent window and size */
     if (vout->b_fullscreen)
     {
-        p_sys->embed = NULL;
         p_sys->parent = screen->root;
         width = screen->width_in_pixels;
         height = screen->height_in_pixels;
     }
     else
     {
-        p_sys->embed = vout_RequestXWindow (vout, &(int){ 0 }, &(int){ 0 },
-                                            &width, &height);
-        if (p_sys->embed == NULL)
-        {
-            msg_Err (vout, "cannot get parent window");
-            return VLC_EGENERIC;
-        }
         p_sys->parent = p_sys->embed->handle.xid;
+
+        /* Subscribe to parent window resize events */
+        const uint32_t value = XCB_EVENT_MASK_STRUCTURE_NOTIFY;
+        xcb_change_window_attributes (p_sys->conn, p_sys->parent,
+                                      XCB_CW_EVENT_MASK, &value);
+
+        xcb_get_geometry_cookie_t ck;
+        ck = xcb_get_geometry (p_sys->conn, p_sys->parent);
+
+        xcb_get_geometry_reply_t *geo;
+        xcb_generic_error_t *err;
+        geo = xcb_get_geometry_reply (p_sys->conn, ck, &err);
+        width = geo->width;
+        height = geo->height;
+        free (geo);
     }
 
-    /* FIXME: incorrect placement if resize now */
     vout_PlacePicture (vout, width, height, &x, &y, &width, &height);
 
     /* FIXME: I don't get the subtlety between output and fmt_out here */
@@ -505,8 +522,6 @@ static void Deinit (vout_thread_t *vout)
 
     xcb_unmap_window (p_sys->conn, p_sys->window);
     xcb_destroy_window (p_sys->conn, p_sys->window);
-    vout_ReleaseWindow (p_sys->embed);
-    p_sys->embed = NULL;
 }
 
 /**
@@ -558,7 +573,7 @@ static int Manage (vout_thread_t *vout)
     xcb_generic_event_t *ev;
 
     while ((ev = xcb_poll_for_event (p_sys->conn)) != NULL)
-        ProcessEvent (vout, ev);
+        ProcessEvent (vout, p_sys->conn, p_sys->window, ev);
 
     if (xcb_connection_has_error (p_sys->conn))
     {
index 51f92c7521e1493b420b4dfdce26bd0f929c0f44..efedd0260944af47b3e2101798748b1d0e967081 100644 (file)
@@ -21,7 +21,8 @@
  ****************************************************************************/
 
 int CheckError (vout_thread_t *, const char *str, xcb_void_cookie_t);
-int ProcessEvent (vout_thread_t *, xcb_generic_event_t *);
+int ProcessEvent (vout_thread_t *, xcb_connection_t *, xcb_window_t,
+                  xcb_generic_event_t *);
 
 typedef struct key_handler_t key_handler_t;
 key_handler_t *CreateKeyHandler (vlc_object_t *, xcb_connection_t *);