vlcplugin_gtk.cpp 19.3 KB
Newer Older
1 2 3
/*****************************************************************************
 * vlcplugin_gtk.cpp: a VLC plugin for Mozilla (GTK+ interface)
 *****************************************************************************
4
 * Copyright (C) 2002-2012 VLC authors and VideoLAN
5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23
 * $Id$
 *
 * Authors: Cheng Sun <chengsun9@gmail.com>
 *
 * This program 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 of the License, or
 * (at your option) any later version.
 *
 * This program 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 General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
 *****************************************************************************/

24 25 26 27
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif

28 29
#include "vlcplugin_gtk.h"
#include <gdk/gdkx.h>
30
#include <gdk/gdkkeysyms.h>
31 32
#include <cstring>

Cheng Sun's avatar
Cheng Sun committed
33 34
static uint32_t get_xid(GtkWidget *widget)
{
35 36 37 38 39 40 41 42
    GdkDrawable *video_drawable = gtk_widget_get_window(widget);
    return (uint32_t)gdk_x11_drawable_get_xid(video_drawable);
}

VlcPluginGtk::VlcPluginGtk(NPP instance, NPuint16_t mode) :
    VlcPluginBase(instance, mode),
    parent(NULL),
    parent_vbox(NULL),
43
    video_container(NULL),
Hugo Beauzée-Luyssen's avatar
Hugo Beauzée-Luyssen committed
44
    fullscreen_win(NULL),
45
    toolbar(NULL),
46 47
    time_slider(NULL),
    vol_slider(NULL),
48
    is_fullscreen(false),
49
    is_toolbar_visible(false),
50
    m_timer_update_timeout( 0 )
51
{
52
    memset(&video_xwindow, 0, sizeof(Window));
53 54 55 56 57 58
    GtkIconTheme *icon_theme = gtk_icon_theme_get_default();
    cone_icon = gdk_pixbuf_copy(gtk_icon_theme_load_icon(
                    icon_theme, "vlc", 128, GTK_ICON_LOOKUP_FORCE_SIZE, NULL));
    if (!cone_icon) {
        fprintf(stderr, "WARNING: could not load VLC icon\n");
    }
59 60
}

61 62 63 64 65 66 67 68 69
VlcPluginGtk::~VlcPluginGtk()
{
    {
        std::lock_guard<std::mutex> lock( m_timer_lock );
        if ( m_timer_update_timeout != 0 )
            g_source_remove( m_timer_update_timeout );
    }
}

70 71
void VlcPluginGtk::set_player_window()
{
72 73
    player().get_mp().setXwindow( video_xwindow);
    player().get_mp().setMouseInput( false );
74 75 76 77
}

void VlcPluginGtk::toggle_fullscreen()
{
78
    set_fullscreen(!get_fullscreen());
79 80
}

81
void VlcPluginGtk::do_set_fullscreen(bool yes)
82
{
83 84 85 86 87
    /* we have to reparent windows */
    /* note that the xid of video_container changes after reparenting */
    Display *display = get_display();
    g_signal_handler_block(video_container, video_container_size_handler_id);

Cheng Sun's avatar
Cheng Sun committed
88 89
    XUnmapWindow(display, video_xwindow);
    XReparentWindow(display, video_xwindow,
90
                    gdk_x11_get_default_root_xwindow(), 0, 0);
Cheng Sun's avatar
Cheng Sun committed
91
    if (yes) {
92 93 94 95 96
        g_object_ref(G_OBJECT(parent_vbox));
        gtk_container_remove(GTK_CONTAINER(parent), parent_vbox);
        gtk_container_add(GTK_CONTAINER(fullscreen_win), parent_vbox);
        g_object_unref(G_OBJECT(parent_vbox));
        gtk_widget_show_all(fullscreen_win);
97 98 99
        gtk_window_fullscreen(GTK_WINDOW(fullscreen_win));
    } else {
        gtk_widget_hide(fullscreen_win);
100 101 102 103
        g_object_ref(G_OBJECT(parent_vbox));
        gtk_container_remove(GTK_CONTAINER(fullscreen_win), parent_vbox);
        gtk_container_add(GTK_CONTAINER(parent), parent_vbox);
        g_object_unref(G_OBJECT(parent_vbox));
104 105
        gtk_widget_show_all(GTK_WIDGET(parent));
    }
106
    XSync(get_display(), false);
107
    XReparentWindow(display, video_xwindow, get_xid(video_container), 0, 0);
Cheng Sun's avatar
Cheng Sun committed
108

109 110
//    libvlc_set_fullscreen(libvlc_media_player, yes);
    g_signal_handler_unblock(video_container, video_container_size_handler_id);
111 112
    gtk_widget_queue_resize(video_container);
    update_controls();
113 114

    is_fullscreen = yes;
115 116
}

117 118
void VlcPluginGtk::set_fullscreen(int yes)
{
119
    if (!get_options().get_enable_fs()) return;
120 121 122 123 124 125 126 127
    if (yes == is_fullscreen) return;
    if (yes) {
        gtk_widget_show(fullscreen_win);
    } else {
        gtk_widget_hide(fullscreen_win);
    }
}

128
bool VlcPluginGtk::get_fullscreen()
129
{
130
    return is_fullscreen;
131 132
}

133
void VlcPluginGtk::set_toolbar_visible(bool yes)
134
{
135 136 137 138 139 140 141 142 143 144 145 146
    if (yes == is_toolbar_visible) return;

    if (yes) {
        gtk_box_pack_start(GTK_BOX(parent_vbox), toolbar, false, false, 0);
        gtk_widget_show_all(toolbar);
        update_controls();
        g_object_unref(G_OBJECT(toolbar));
    } else {
        g_object_ref(G_OBJECT(toolbar));
        gtk_widget_hide(toolbar);
        gtk_container_remove(GTK_CONTAINER(parent_vbox), toolbar);
    }
147 148
    resize_windows();
    gtk_container_resize_children(GTK_CONTAINER(parent));
149
    is_toolbar_visible = yes;
150 151
}

152
bool VlcPluginGtk::get_toolbar_visible()
153
{
154
    return is_toolbar_visible;
155 156
}

157 158 159 160 161
void VlcPluginGtk::resize_video_xwindow(GdkRectangle *rect)
{
    Display *display = get_display();
    XResizeWindow(display, video_xwindow,
                  rect->width, rect->height);
162
    XSync(display, false);
163 164
}

165 166 167 168 169 170 171 172 173 174
struct tool_actions_t
{
    const gchar *stock_id;
    vlc_toolbar_clicked_t clicked;
};
static const tool_actions_t tool_actions[] = {
    {GTK_STOCK_MEDIA_PLAY, clicked_Play},
    {GTK_STOCK_MEDIA_PAUSE, clicked_Pause},
    {GTK_STOCK_MEDIA_STOP, clicked_Stop},
    {"gtk-volume-muted", clicked_Mute},
175 176
    {"gtk-volume-unmuted", clicked_Unmute},
    {GTK_STOCK_FULLSCREEN, clicked_Fullscreen}
177 178
};

Cheng Sun's avatar
Cheng Sun committed
179
static void toolbar_handler(GtkToolButton *btn, gpointer user_data)
180
{
Cheng Sun's avatar
Cheng Sun committed
181
    VlcPluginGtk *plugin = (VlcPluginGtk *) user_data;
182
    const gchar *stock_id = gtk_tool_button_get_stock_id(btn);
Hugo Beauzée-Luyssen's avatar
Hugo Beauzée-Luyssen committed
183 184 185
    for (auto a : tool_actions ) {
        if (!strcmp(stock_id, a.stock_id)) {
            plugin->control_handler(a.clicked);
186 187 188
            return;
        }
    }
Cheng Sun's avatar
Cheng Sun committed
189
    fprintf(stderr, "WARNING: No idea what toolbar button you just clicked on (%s)\n", stock_id?stock_id:"NULL");
190 191
}

192 193 194 195
static void menu_handler(GtkMenuItem *menuitem, gpointer user_data)
{
    VlcPluginGtk *plugin = (VlcPluginGtk *) user_data;
    const gchar *stock_id = gtk_menu_item_get_label(GTK_MENU_ITEM(menuitem));
196 197 198 199
    if (!strcmp(stock_id, VLCPLUGINGTK_MENU_TOOLBAR)) {
        plugin->set_toolbar_visible(gtk_check_menu_item_get_active(GTK_CHECK_MENU_ITEM(menuitem)));
        return;
    }
Hugo Beauzée-Luyssen's avatar
Hugo Beauzée-Luyssen committed
200 201 202 203
    for (auto a : tool_actions)
    {
        if (!strcmp(stock_id, a.stock_id)) {
            plugin->control_handler(a.clicked);
204 205 206 207 208 209
            return;
        }
    }
    fprintf(stderr, "WARNING: No idea what menu item you just clicked on (%s)\n", stock_id?stock_id:"NULL");
}

210
void VlcPluginGtk::popup_menu()
211 212
{
    /* construct menu */
213
    GtkWidget *popupmenu = gtk_menu_new();
214 215 216 217
    GtkWidget *menuitem;

    /* play/pause */
    menuitem = gtk_image_menu_item_new_from_stock(
218
                        player().mlp().isPlaying() ?
219 220 221
                        GTK_STOCK_MEDIA_PAUSE :
                        GTK_STOCK_MEDIA_PLAY, NULL);
    g_signal_connect(G_OBJECT(menuitem), "activate", G_CALLBACK(menu_handler), this);
222
    gtk_menu_shell_append(GTK_MENU_SHELL(popupmenu), menuitem);
223 224 225 226
    /* stop */
    menuitem = gtk_image_menu_item_new_from_stock(
                                GTK_STOCK_MEDIA_STOP, NULL);
    g_signal_connect(G_OBJECT(menuitem), "activate", G_CALLBACK(menu_handler), this);
227
    gtk_menu_shell_append(GTK_MENU_SHELL(popupmenu), menuitem);
228
    /* set fullscreen */
229
    if (get_options().get_enable_fs()) {
230 231 232 233 234
        menuitem = gtk_image_menu_item_new_from_stock(
                                    GTK_STOCK_FULLSCREEN, NULL);
        g_signal_connect(G_OBJECT(menuitem), "activate", G_CALLBACK(menu_handler), this);
        gtk_menu_shell_append(GTK_MENU_SHELL(popupmenu), menuitem);
    }
235 236 237 238 239 240
    /* toolbar */
    menuitem = gtk_check_menu_item_new_with_label(
                                VLCPLUGINGTK_MENU_TOOLBAR);
    gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(menuitem), get_toolbar_visible());
    g_signal_connect(G_OBJECT(menuitem), "activate", G_CALLBACK(menu_handler), this);
    gtk_menu_shell_append(GTK_MENU_SHELL(popupmenu), menuitem);
241

242
    /* show menu */
243
    gtk_widget_show_all(popupmenu);
244
    gtk_menu_attach_to_widget(GTK_MENU(popupmenu), video_container, NULL);
245 246
    gtk_menu_popup(GTK_MENU(popupmenu), NULL, NULL, NULL, NULL,
                   0, gtk_get_current_event_time());
247 248
}

Hugo Beauzée-Luyssen's avatar
Hugo Beauzée-Luyssen committed
249
static bool video_button_handler(GtkWidget*, GdkEventButton *event, gpointer user_data)
250 251 252
{
    VlcPluginGtk *plugin = (VlcPluginGtk *) user_data;
    if (event->button == 3 && event->type == GDK_BUTTON_PRESS) {
253
        plugin->popup_menu();
254 255
        return true;
    }
256 257 258
    if (event->button == 1 && event->type == GDK_2BUTTON_PRESS) {
        plugin->toggle_fullscreen();
    }
259 260 261
    return false;
}

Hugo Beauzée-Luyssen's avatar
Hugo Beauzée-Luyssen committed
262
static bool video_popup_handler(GtkWidget*, gpointer user_data)
263
{
264
    VlcPluginGtk *plugin = (VlcPluginGtk *) user_data;
265
    plugin->popup_menu();
266 267 268
    return true;
}

Hugo Beauzée-Luyssen's avatar
Hugo Beauzée-Luyssen committed
269
static bool video_size_handler(GtkWidget*, GdkRectangle *rect, gpointer user_data)
270
{
271 272 273 274 275
    VlcPluginGtk *plugin = (VlcPluginGtk *) user_data;
    plugin->resize_video_xwindow(rect);
    return true;
}

Hugo Beauzée-Luyssen's avatar
Hugo Beauzée-Luyssen committed
276
static bool video_expose_handler(GtkWidget*, GdkEvent *event, gpointer user_data)
277 278 279 280 281 282 283
{
    VlcPluginGtk *plugin = (VlcPluginGtk *) user_data;
    GdkEventExpose *event_expose = (GdkEventExpose *) event;
    GdkWindow *window = event_expose->window;
    GdkPixbuf *cone_icon = plugin->cone_icon;
    if (!cone_icon) return false;

284 285 286 287 288 289 290 291 292
    int winwidth, winheight;
#   if GTK_CHECK_VERSION(2, 24, 0)
        winwidth  = gdk_window_get_width(window);
        winheight = gdk_window_get_height(window);
#   else
        gdk_drawable_get_size(GDK_DRAWABLE(window), &winwidth, &winheight);
#   endif

    int iconwidth  = gdk_pixbuf_get_width(cone_icon),
293
        iconheight = gdk_pixbuf_get_height(cone_icon);
294 295 296 297 298 299 300 301 302 303
    double widthratio  = (double) winwidth / iconwidth,
           heightratio = (double) winheight / iconheight;
    double sizeratio = widthratio < heightratio ? widthratio : heightratio;
    if (sizeratio < 1.0) {
        cone_icon = gdk_pixbuf_scale_simple(cone_icon, iconwidth * sizeratio, iconheight * sizeratio, GDK_INTERP_BILINEAR);
        if (!cone_icon) return false;
        iconwidth  = gdk_pixbuf_get_width(cone_icon);
        iconheight = gdk_pixbuf_get_height(cone_icon);
    }

304 305 306 307 308
    cairo_t *cr = gdk_cairo_create(window);
    gdk_cairo_set_source_pixbuf(cr, cone_icon,
            (winwidth-iconwidth)/2.0, (winheight-iconheight)/2.0);
    gdk_cairo_region(cr, event_expose->region);
    cairo_fill(cr);
309
    cairo_destroy(cr);
310 311 312 313

    return true;
}

314
gboolean VlcPluginGtk::update_time_slider(gpointer user_data)
315
{
Cheng Sun's avatar
Cheng Sun committed
316
    VlcPluginGtk *plugin = (VlcPluginGtk *) user_data;
317

318 319 320 321 322
    std::lock_guard<std::mutex> lock( plugin->m_timer_lock );

    auto pos = plugin->player().get_mp().position() * 100.0f;
    gtk_range_set_value( GTK_RANGE( plugin->time_slider ), pos );
    plugin->m_timer_update_timeout = 0;
323 324 325
    return FALSE;
}

Hugo Beauzée-Luyssen's avatar
Hugo Beauzée-Luyssen committed
326
static bool time_slider_handler(GtkRange*, GtkScrollType, gdouble value, gpointer user_data)
327 328
{
    VlcPluginGtk *plugin = (VlcPluginGtk *) user_data;
329
    plugin->getMD().setPosition( value / 100.0 );
330 331 332
    return false;
}

Hugo Beauzée-Luyssen's avatar
Hugo Beauzée-Luyssen committed
333
static bool vol_slider_handler(GtkRange*, GtkScrollType, gdouble value, gpointer user_data)
334 335
{
    VlcPluginGtk *plugin = (VlcPluginGtk *) user_data;
336
    plugin->getMD().setVolume( value );
337
    return false;
338 339
}

340 341 342
static void fullscreen_win_visibility_handler(GtkWidget *widget, gpointer user_data)
{
    VlcPluginGtk *plugin = (VlcPluginGtk *) user_data;
343
    plugin->do_set_fullscreen(gtk_widget_get_visible(widget));
344 345
}

Hugo Beauzée-Luyssen's avatar
Hugo Beauzée-Luyssen committed
346
static gboolean fullscreen_win_keypress_handler(GtkWidget*, GdkEventKey *event, gpointer user_data)
347 348 349 350
{
    VlcPluginGtk *plugin = (VlcPluginGtk *) user_data;
    switch (event->keyval)
    {
351
    case GDK_KEY_space:
352
        plugin->player().mlp().pause();
353
        return True;
354 355 356 357 358 359 360 361
    case GDK_KEY_Escape:
        plugin->set_fullscreen(false);
        return True;
    default:
        return False;
    }
}

362 363
void VlcPluginGtk::update_controls()
{
364
    auto state = player().get_mp().state();
365 366 367 368
    if ( state == libvlc_Stopped || state == libvlc_Ended || state == libvlc_Error ) {
        XUnmapWindow(display, video_xwindow);
    } else {
        XMapWindow(display, video_xwindow);
369 370
    }

371 372 373 374
    if (get_toolbar_visible()) {
        GtkToolItem *toolbutton;

        /* play/pause button */
375
        const gchar *stock_id = player().mlp().isPlaying() ? GTK_STOCK_MEDIA_PAUSE : GTK_STOCK_MEDIA_PLAY;
376 377 378 379 380 381 382 383 384
        toolbutton = gtk_toolbar_get_nth_item(GTK_TOOLBAR(toolbar), 0);
        if (strcmp(gtk_tool_button_get_stock_id(GTK_TOOL_BUTTON(toolbutton)), stock_id)) {
            gtk_tool_button_set_stock_id(GTK_TOOL_BUTTON(toolbutton), stock_id);
            /* work around firefox not displaying the icon properly after change */
            g_object_ref(toolbutton);
            gtk_container_remove(GTK_CONTAINER(toolbar), GTK_WIDGET(toolbutton));
            gtk_toolbar_insert(GTK_TOOLBAR(toolbar), toolbutton, 0);
            g_object_unref(toolbutton);
        }
385

386
        /* toolbar sensitivity */
387
        gtk_widget_set_sensitive( toolbar, true );
388

389
        /* time slider */
390
        if (!player().get_mp().isSeekable()) {
391 392 393 394 395
            gtk_widget_set_sensitive(time_slider, false);
            gtk_range_set_value(GTK_RANGE(time_slider), 0);
        } else {
            gtk_widget_set_sensitive(time_slider, true);
        }
396

397 398
        gtk_widget_show_all(toolbar);
    }
399 400 401 402
}

bool VlcPluginGtk::create_windows()
{
403 404
    display = ( (NPSetWindowCallbackStruct *) npwindow.ws_info )->display;

405
    Window socket = (Window) npwindow.window;
406
    GdkColor color_bg;
407
    gdk_color_parse(get_options().get_bg_color().c_str(), &color_bg);
408 409

    parent = gtk_plug_new(socket);
410
    gtk_widget_modify_bg(parent, GTK_STATE_NORMAL, &color_bg);
411 412 413 414
    gtk_widget_add_events(parent,
            GDK_BUTTON_PRESS_MASK
          | GDK_BUTTON_RELEASE_MASK);
    g_signal_connect(G_OBJECT(parent), "button-press-event", G_CALLBACK(video_button_handler), this);
415 416 417 418

    parent_vbox = gtk_vbox_new(false, 0);
    gtk_container_add(GTK_CONTAINER(parent), parent_vbox);

419
    video_container = gtk_drawing_area_new();
420
    gtk_widget_modify_bg(video_container, GTK_STATE_NORMAL, &color_bg);
421
    gtk_widget_add_events(video_container,
422 423
            GDK_BUTTON_PRESS_MASK
          | GDK_BUTTON_RELEASE_MASK);
424
    g_signal_connect(G_OBJECT(video_container), "expose-event", G_CALLBACK(video_expose_handler), this);
425 426 427
    g_signal_connect(G_OBJECT(video_container), "button-press-event", G_CALLBACK(video_button_handler), this);
    g_signal_connect(G_OBJECT(video_container), "popup-menu", G_CALLBACK(video_popup_handler), this);
    gtk_box_pack_start(GTK_BOX(parent_vbox), video_container, true, true, 0);
428 429 430

    gtk_widget_show_all(parent);

431 432
    /* fullscreen top-level */
    fullscreen_win = gtk_window_new(GTK_WINDOW_TOPLEVEL);
433
    gtk_widget_modify_bg(fullscreen_win, GTK_STATE_NORMAL, &color_bg);
434 435 436 437
    gtk_window_set_decorated(GTK_WINDOW(fullscreen_win), false);
    g_signal_connect(G_OBJECT(fullscreen_win), "delete-event", G_CALLBACK(gtk_widget_hide_on_delete), this);
    g_signal_connect(G_OBJECT(fullscreen_win), "show", G_CALLBACK(fullscreen_win_visibility_handler), this);
    g_signal_connect(G_OBJECT(fullscreen_win), "hide", G_CALLBACK(fullscreen_win_visibility_handler), this);
438
    g_signal_connect(G_OBJECT(fullscreen_win), "key_press_event", G_CALLBACK(fullscreen_win_keypress_handler), this);
439 440 441 442 443 444

    /* actual video window */
    /* libvlc is handed this window's xid. A raw X window is used because
     * GTK+ is incapable of reparenting without changing xid
     */
    Display *display = get_display();
445 446 447 448 449
    Colormap colormap = DefaultColormap(display, DefaultScreen(display));
    bg_color.red   = color_bg.red;
    bg_color.green = color_bg.green;
    bg_color.blue  = color_bg.blue;
    XAllocColor(display, colormap, &bg_color);
450 451
    video_xwindow = XCreateSimpleWindow(display, get_xid(video_container), 0, 0,
                   1, 1,
452
                   0, bg_color.pixel, bg_color.pixel);
453 454 455 456 457 458

    /* connect video_container resizes to video_xwindow */
    video_container_size_handler_id = g_signal_connect(
                G_OBJECT(video_container), "size-allocate",
                G_CALLBACK(video_size_handler), this);
    gtk_widget_queue_resize_no_redraw(video_container);
Cheng Sun's avatar
Cheng Sun committed
459 460 461

    /*** TOOLBAR ***/

462
    toolbar = gtk_toolbar_new();
463
    g_object_ref(G_OBJECT(toolbar));
464
    gtk_toolbar_set_style(GTK_TOOLBAR(toolbar), GTK_TOOLBAR_ICONS);
Cheng Sun's avatar
Cheng Sun committed
465
    gtk_toolbar_set_icon_size(GTK_TOOLBAR(toolbar), GTK_ICON_SIZE_SMALL_TOOLBAR);
466 467 468 469 470
    GtkToolItem *toolitem;
    /* play/pause */
    toolitem = gtk_tool_button_new_from_stock(GTK_STOCK_MEDIA_PLAY);
    g_signal_connect(G_OBJECT(toolitem), "clicked", G_CALLBACK(toolbar_handler), this);
    gtk_toolbar_insert(GTK_TOOLBAR(toolbar), toolitem, -1);
471 472 473 474 475 476 477 478 479
    m_player.get_mp().eventManager().onPaused([this, toolitem]() {
        gtk_tool_button_set_stock_id(GTK_TOOL_BUTTON(toolitem), GTK_STOCK_MEDIA_PLAY);
    });
    m_player.get_mp().eventManager().onPlaying([this, toolitem]() {
        gtk_tool_button_set_stock_id(GTK_TOOL_BUTTON(toolitem), GTK_STOCK_MEDIA_PAUSE);
    });
    m_player.get_mp().eventManager().onStopped([this, toolitem]() {
        gtk_tool_button_set_stock_id(GTK_TOOL_BUTTON(toolitem), GTK_STOCK_MEDIA_PLAY);
    });
480 481 482 483 484 485 486 487 488
    /* stop */
    toolitem = gtk_tool_button_new_from_stock(GTK_STOCK_MEDIA_STOP);
    g_signal_connect(G_OBJECT(toolitem), "clicked", G_CALLBACK(toolbar_handler), this);
    gtk_toolbar_insert(GTK_TOOLBAR(toolbar), toolitem, -1);

    /* time slider */
    toolitem = gtk_tool_item_new();
    time_slider = gtk_hscale_new_with_range(0, 100, 10);
    gtk_scale_set_draw_value(GTK_SCALE(time_slider), false);
489
    gtk_range_set_increments(GTK_RANGE(time_slider), 2, 10);
490 491 492 493
    g_signal_connect(G_OBJECT(time_slider), "change-value", G_CALLBACK(time_slider_handler), this);
    gtk_container_add(GTK_CONTAINER(toolitem), time_slider);
    gtk_tool_item_set_expand(toolitem, true);
    gtk_toolbar_insert(GTK_TOOLBAR(toolbar), toolitem, -1);
494 495 496 497 498
    m_player.get_mp().eventManager().onPositionChanged([this](float) {
        std::lock_guard<std::mutex> lock( m_timer_lock );
        if ( m_timer_update_timeout == 0 )
            m_timer_update_timeout = g_timeout_add( 100, update_time_slider, (gpointer)this);
    });
499

500 501
    /* volume slider */
    toolitem = gtk_tool_item_new();
502
    vol_slider = gtk_hscale_new_with_range(0, 200, 10);
503
    gtk_range_set_increments(GTK_RANGE(vol_slider), 5, 20);
504 505 506 507 508 509 510 511
    gtk_scale_set_draw_value(GTK_SCALE(vol_slider), false);
    g_signal_connect(G_OBJECT(vol_slider), "change-value", G_CALLBACK(vol_slider_handler), this);
    gtk_range_set_value(GTK_RANGE(vol_slider), 100);
    gtk_widget_set_size_request(vol_slider, 100, -1);
    gtk_container_add(GTK_CONTAINER(toolitem), vol_slider);
    gtk_tool_item_set_expand(toolitem, false);
    gtk_toolbar_insert(GTK_TOOLBAR(toolbar), toolitem, -1);

512 513 514 515 516 517 518 519 520
    return true;
}

bool VlcPluginGtk::resize_windows()
{
    GtkRequisition req;
    req.width = npwindow.width;
    req.height = npwindow.height;
    gtk_widget_size_request(parent, &req);
Jean-Baptiste Kempf's avatar
Jean-Baptiste Kempf committed
521
    return true;
522 523 524 525
}

bool VlcPluginGtk::destroy_windows()
{
526
    Display *display = get_display();
527 528 529 530

    /* destroy x window */
    XDestroyWindow(display, video_xwindow);

531 532 533 534
    /* destroy GTK top-levels */
    gtk_widget_destroy(parent);
    gtk_widget_destroy(fullscreen_win);

535
    /* free colors */
536 537
    Colormap colormap = DefaultColormap(display, DefaultScreen(display));
    XFreeColors(display, colormap, &bg_color.pixel, 1, 0);
Jean-Baptiste Kempf's avatar
Jean-Baptiste Kempf committed
538
    return true;
539
}