Пример #1
0
static int gui_update()
{
	int i, count;

	if (gui->need_update==1) {
		GuiWidget *cur_widget;
		cur_widget = (GuiWidget*)stack_get(gui->win_stack, 0);
		widget_update(cur_widget);

		count = stack_count(gui->win_stack);
		for (i=1; i<count -1; i++) {
			cur_widget = (GuiWidget *) stack_get(gui->win_stack, i);

			if (cur_widget && window_get_update(cur_widget) == 1) {
				widget_update(cur_widget);
				window_set_update(cur_widget, 0);
			}
		}
		widget_update(GET_TOP_WINDOW);

		SDL_Flip(screen);
		gui->need_update = 0;
		return 1;
	}

	return 0;
}
Пример #2
0
void widget_enable ( widget *widget )
{
    if ( widget && !widget->enabled ) {
        widget->enabled = TRUE;
        widget_update ( widget );
        widget_update ( widget->parent );
    }
}
Пример #3
0
void widget_disable ( widget *widget )
{
    if ( widget && widget->enabled ) {
        widget->enabled = FALSE;
        widget_update ( widget );
        widget_update ( widget->parent );
    }
}
Пример #4
0
Save_Widget::Save_Widget() :
    _plugin      (0),
    _codec_widget(0)
{
    // Create widgets.

    Group_Box * codec_group = new Group_Box(label_codec_group);

    _codec_widget = new Radio_Button_Group(label_codec());

    // Layout.

    Layout_Item::create_group(List<Layout_Item *>() <<
        _codec_widget);

    Vertical_Layout * layout = new Vertical_Layout(this);
    layout->spacing(Style::global()->spacing_large());

    layout->add(codec_group);
    codec_group->layout()->add(_codec_widget);

    layout->add_stretch();

    // Initialize.

    plugin_update();
    widget_update();

    // Callbacks.

    _codec_widget->signal.set(this, codec_callback);
}
Пример #5
0
Save_Widget::Save_Widget() :
    _plugin            (0),
    _compression_widget(0)
{
    //DJV_DEBUG("Save_Widget::Save_Widget");

    // Create widgets.

    Group_Box * group = new Group_Box(label_compression_group);

    _compression_widget = new Radio_Button_Group(label_compression());

    // Layout.

    Vertical_Layout * layout = new Vertical_Layout(this);
    layout->margin(Style::global()->margin_large());
    layout->spacing(Style::global()->spacing_large());

    layout->add(group);
    group->layout()->add(_compression_widget);

    layout->add_stretch();

    // Initialize.

    plugin_update();
    widget_update();

    // Callbacks.

    _compression_widget->signal.set(this, compression_callback);
}
Пример #6
0
void Magnify_Dialog::set(const View_Widget * in, const V2i & pick)
{
    _view = in;
    _pick = pick;

    widget_update();
}
Пример #7
0
void File_Browser::set(const File & in)
{
    if (in == _value)
    {
        return;
    }

    //DJV_DEBUG("File_Browser::set");
    //DJV_DEBUG_PRINT("in = " << in);

    const String directory = _value.path();

    _value = in;

    if (_seq && _value.is_seq_valid())
    {
        _value.type(File::SEQ);
    }

    if (_value.path() != directory)
    {
        _directory_prev = directory;

        directory_update();
    }

    widget_update();
}
Пример #8
0
// set the default text to display
void textbox_text ( textbox *tb, const char *text )
{
    tb->update = TRUE;
    g_free ( tb->text );
    const gchar *last_pointer = NULL;

    if ( g_utf8_validate ( text, -1, &last_pointer ) ) {
        tb->text = g_strdup ( text );
    }
    else {
        if ( last_pointer != NULL ) {
            // Copy string up to invalid character.
            tb->text = g_strndup ( text, ( last_pointer - text ) );
        }
        else {
            tb->text = g_strdup ( "Invalid UTF-8 string." );
        }
    }
    __textbox_update_pango_text ( tb );
    if ( tb->flags & TB_AUTOWIDTH ) {
        textbox_moveresize ( tb, tb->widget.x, tb->widget.y, tb->widget.w, tb->widget.h );
        if ( WIDGET ( tb )->parent ) {
            widget_update ( WIDGET ( tb )->parent );
        }
    }

    tb->cursor = MAX ( 0, MIN ( ( int ) g_utf8_strlen ( tb->text, -1 ), tb->cursor ) );
    widget_queue_redraw ( WIDGET ( tb ) );
}
Пример #9
0
Файл: box.c Проект: yusiwen/rofi
static void box_resize ( widget *widget, short w, short h )
{
    box *b = (box *) widget;
    if ( b->widget.w != w || b->widget.h != h ) {
        b->widget.w = w;
        b->widget.h = h;
        widget_update ( widget );
    }
}
Пример #10
0
void Magnify_Dialog::update(const View_Widget * in)
{
    if (in != _view || ! shown() || ! visible())
    {
        return;
    }

    widget_update();
}
Пример #11
0
void Display_Profile_Dialog::set(
    const View_Widget * in,
    const Display_Profile & value)
{
    _view = in;
    _value = value;

    widget_update();
}
Пример #12
0
Save_Widget::Save_Widget() :
    _plugin              (0),
    _color_profile_widget(0),
    _black_widget        (0),
    _white_widget        (0),
    _gamma_widget        (0)
{
    // Create color profile widgets.

    Group_Box * color_profile_group =
        new Group_Box(label_color_profile_group);

    _color_profile_widget = new Radio_Button_Group(label_color_profile());

    Group_Box * film_print_group = new Group_Box(label_film_print_group);

    _black_widget = new Int_Edit_Slider(0, 1023);

    _white_widget = new Int_Edit_Slider(0, 1023);

    _gamma_widget = new Float_Edit_Slider(0.01, 4.0);

    // Layout.

    Vertical_Layout * layout = new Vertical_Layout(this);
    layout->margin(Style::global()->margin_large());
    layout->spacing(Style::global()->spacing_large());

    layout->add(color_profile_group);
    color_profile_group->layout()->add(_color_profile_widget);

    color_profile_group->layout()->add(film_print_group);
    Form_Widget * form_widget = new Form_Widget;
    film_print_group->layout()->add(form_widget);
    form_widget->add_row(label_film_print_black, _black_widget);
    form_widget->add_row(label_film_print_white, _white_widget);
    form_widget->add_row(label_film_print_gamma, _gamma_widget);

    layout->add_stretch();

    // Initialize.

    _black_widget->default_value(Save::Options().film_print.black);
    _white_widget->default_value(Save::Options().film_print.white);
    _gamma_widget->default_value(Save::Options().film_print.gamma);

    plugin_update();
    widget_update();

    // Callbacks.

    _color_profile_widget->signal.set(this, color_profile_callback);
    _black_widget->signal.set(this, black_callback);
    _white_widget->signal.set(this, white_callback);
    _gamma_widget->signal.set(this, gamma_callback);
}
Пример #13
0
Text_Display::Text_Display(const String & in) :
    _value(in),
    _widget(0)
{
    debug_path("Text_Display");

    add(_widget = new Widget);

    widget_update();
}
Пример #14
0
void Display_Profile_Dialog::update(
    const View_Widget * in,
    const Display_Profile & value)
{
    if (in != _view)
    {
        return;
    }

    _value = value;

    widget_update();
}
Пример #15
0
void Text_Display::set(const String & in)
{
    if (in == _value)
    {
        return;
    }

    //DJV_DEBUG("Text_Display::set");
    //DJV_DEBUG_PRINT("in = " << in);

    _value = in;

    widget_update();
}
Пример #16
0
Application_Message_Dialog::Application_Message_Dialog() :
    Dialog("Messages"),
    _show        (true),
    _widget      (0),
    _show_widget (0),
    _clear_widget(0),
    _close_widget(0)
{
    // Create widgets.

    _widget = new Multiline_Text_Display;

    _show_widget = new Check_Button("&Show");

    _clear_widget = new Push_Button("&Clear");

    _close_widget = new Push_Button("Clos&e");

    // Layout.

    Vertical_Layout * layout = new Vertical_Layout(this);
    layout->add(_widget);
    layout->stretch(_widget);

    Horizontal_Layout * layout_h = new Horizontal_Layout(layout);
    layout_h->margin(0);
    layout_h->add(_show_widget);
    layout_h->add_stretch();
    layout_h->add(_clear_widget);
    layout_h->add(_close_widget);
    layout_h->add_spacer(Layout::window_handle_size());

    // Preferences.

    Prefs prefs(Prefs::prefs_global(), "application_message_dialog");
    Prefs::get_(&prefs, "show", &_show);

    // Initialize.

    widget_update();
    dialog_update();

    size(size_hint());

    // Callbacks.

    _show_widget->signal.set(this, show_callback);
    _clear_widget->signal.set(this, clear_callback);
    _close_widget->signal.set(this, close_callback);
}
Пример #17
0
void File_Browser::seq(Seq::COMPRESS in)
{
    if (in == _seq)
    {
        return;
    }

    _seq = in;

    _prefs->seq(_seq);

    directory_update();
    widget_update();
    menu_update();
}
Пример #18
0
void Application_Message_Dialog::set(const String & in)
{
    _list.push_front(in);

    if (_list.size() > 100)
    {
        _list.pop_back();
    }

    widget_update();

    if (_show)
    {
        show();
    }
}
Пример #19
0
void File_Browser::show()
{
    //DJV_DEBUG("File_Browser::show");

    if (! shown())
    {
        //_value = File_Util::path_absolute(".");

        directory_update();
        widget_update();

        _value_widget->take_focus();
    }

    Dialog::show();
}
Пример #20
0
Magnify_Dialog::Magnify_Dialog() :
    Dialog("Magnify"),
    _view        (0),
    _zoom        (ZOOM_200),
    _widget      (0),
    _zoom_widget (0),
    _close_widget(0)
{
    // Create widgets.

    _widget = new Magnify_Widget;

    _zoom_widget = new Choice_Widget(label_zoom());

    _close_widget = new Push_Button(label_close);

    // Layout.

    Vertical_Layout * layout = new Vertical_Layout(this);

    layout->add(_widget);
    layout->stretch(_widget);

    Horizontal_Layout * layout_h = new Horizontal_Layout(layout);
    layout_h->margin(0);
    layout_h->add(_zoom_widget);
    layout_h->add_spacer(-1, true);
    layout_h->add(_close_widget);
    layout_h->add_spacer(Layout::window_handle_size());

    // Preferences.

    Prefs prefs(Prefs::prefs(), "magnify_dialog");
    Prefs::get_(&prefs, "zoom", &_zoom);

    // Initialize.

    widget_update();

    size(Vector_Util::max(size_hint(), V2i(300, 300)));

    // Callbacks.

    _zoom_widget->signal.set(this, zoom_callback);

    _close_widget->signal.set(this, close_callback);
}
Пример #21
0
void*
widget_main (struct widget *widget) {
	struct widget_config config = widget_config_defaults;
	widget_init_config_string(widget->config, "date_format", config.date_format);
	widget_init_config_string(widget->config, "time_format", config.time_format);
	widget_init_config_integer(widget->config, "refresh_interval", config.refresh_interval);

	widget_epoll_init(widget);
	while (true) {
		widget_update(widget, config);
		widget_epoll_wait_goto(widget, config.refresh_interval, cleanup);
	}

cleanup:

	widget_epoll_cleanup(widget);
	widget_clean_exit(widget);
}
Пример #22
0
Файл: box.c Проект: yusiwen/rofi
void box_add ( box *box, widget *child, gboolean expand )
{
    if ( box == NULL ) {
        return;
    }
    // Make sure box is width/heigh enough.
    if ( box->type == ROFI_ORIENTATION_VERTICAL ) {
        int width = box->widget.w;
        width         = MAX ( width, child->w + widget_padding_get_padding_width ( WIDGET ( box ) ) );
        box->widget.w = width;
    }
    else {
        int height = box->widget.h;
        height        = MAX ( height, child->h + widget_padding_get_padding_height ( WIDGET ( box ) ) );
        box->widget.h = height;
    }
    child->expand = rofi_theme_get_boolean ( child, "expand", expand );
    g_assert ( child->parent == WIDGET ( box ) );
    box->children = g_list_append ( box->children, (void *) child );
    widget_update ( WIDGET ( box ) );
}
Пример #23
0
void Magnify_Dialog::zoom_callback(int in)
{
    _zoom = static_cast<ZOOM>(in);

    widget_update();
}
Пример #24
0
void Display_Profile_Dialog::widget_callback(const Display_Profile & in)
{
    _value = in;

    widget_update();
}
Пример #25
0
Display_Profile_Dialog::Display_Profile_Dialog() :
    Dialog("Display Profile"),
    signal            (this),
    _view             (0),
    _lut_widget       (0),
    _brightness_widget(0),
    _contrast_widget  (0),
    _saturation_widget(0),
    _gamma_widget     (0),
    _soft_clip_widget (0),
    _close_widget     (0)
{
    // Create LUT widgets.

    Group_Box * lut_group = new Group_Box(label_lut);

    _lut_widget = new File_Edit;

    // Create color widgets.

    Group_Box * color_group = new Group_Box(label_color);

    _brightness_widget = new Float_Edit_Slider;
    _brightness_widget->default_value(_value.color.brightness);
    _brightness_widget->range(0.0, 4.0);

    _contrast_widget = new Float_Edit_Slider;
    _contrast_widget->default_value(_value.color.contrast);
    _contrast_widget->range(0.0, 4.0);

    _saturation_widget = new Float_Edit_Slider;
    _saturation_widget->default_value(_value.color.saturation);
    _saturation_widget->range(0.0, 4.0);

    // Create levels widgets.

    Group_Box * levels_group = new Group_Box(label_levels);

    _levels_in_widget[0] = new Float_Edit_Slider;
    _levels_in_widget[0]->default_value(_value.levels.in_low);
    _levels_in_widget[0]->range(0.0, 1.0);

    _levels_in_widget[1] = new Float_Edit_Slider;
    _levels_in_widget[1]->default_value(_value.levels.in_high);
    _levels_in_widget[1]->range(0.0, 1.0);

    _gamma_widget = new Float_Edit_Slider;
    _gamma_widget->default_value(_value.levels.gamma);
    _gamma_widget->range(0.0, 4.0);

    _levels_out_widget[0] = new Float_Edit_Slider;
    _levels_out_widget[0]->default_value(_value.levels.out_low);
    _levels_out_widget[0]->range(0.0, 1.0);

    _levels_out_widget[1] = new Float_Edit_Slider;
    _levels_out_widget[1]->default_value(_value.levels.out_high);
    _levels_out_widget[1]->range(0.0, 1.0);

    _soft_clip_widget = new Float_Edit_Slider;
    _soft_clip_widget->default_value(_value.soft_clip);
    _soft_clip_widget->range(0.0, 1.0);

    // Create dialog widgets.

    _close_widget = new Push_Button(label_close);

    // Layout.

    Vertical_Layout * layout = new Vertical_Layout(this);

    layout->add(lut_group);
    lut_group->layout()->add(_lut_widget);

    layout->add(color_group);
    Form_Widget * form_widget = new Form_Widget;
    color_group->layout()->add(form_widget);
    form_widget->add_row(label_brightness, _brightness_widget);
    form_widget->add_row(label_contrast, _contrast_widget);
    form_widget->add_row(label_saturation, _saturation_widget);
    
    layout->add(levels_group);
    form_widget = new Form_Widget;
    levels_group->layout()->add(form_widget);
    form_widget->add_row(label_levels_in, _levels_in_widget[0]);
    form_widget->add_row(String(), _levels_in_widget[1]);
    form_widget->add_row(label_gamma, _gamma_widget);
    form_widget->add_row(label_levels_out, _levels_out_widget[0]);
    form_widget->add_row(String(), _levels_out_widget[1]);
    form_widget->add_row(label_soft_clip, _soft_clip_widget);
    
    layout->add_spacer(-1, true);

    Horizontal_Layout * layout_h = new Horizontal_Layout(layout);
    layout_h->margin(0);
    layout_h->add_stretch();
    layout_h->add(_close_widget);
    layout_h->add_spacer(Layout::window_handle_size());

    // Initialize.

    widget_update();

    size(size_hint());

    // Callbacks.

    _lut_widget->signal.set(this, lut_callback);

    _brightness_widget->signal.set(this, brightness_callback);
    _contrast_widget->signal.set(this, contrast_callback);
    _saturation_widget->signal.set(this, saturation_callback);

    _levels_in_widget[0]->signal.set(this, levels_in0_callback);
    _levels_in_widget[1]->signal.set(this, levels_in1_callback);
    _gamma_widget->signal.set(this, gamma_callback);
    _levels_out_widget[0]->signal.set(this, levels_out0_callback);
    _levels_out_widget[1]->signal.set(this, levels_out1_callback);
    _soft_clip_widget->signal.set(this, soft_clip_callback);

    _close_widget->signal.set(this, close_callback);
}
Пример #26
0
void Application_Message_Dialog::clear_callback(bool)
{
    _list.clear();

    widget_update();
}
Пример #27
0
int main ( G_GNUC_UNUSED int argc, G_GNUC_UNUSED char **argv )
{
    {
        box *b = box_create ( "box", BOX_HORIZONTAL );
        //box_set_padding ( b, 5 );
        widget_resize ( WIDGET (b), 100, 20);

        widget *wid1 = g_malloc0(sizeof(widget));
        box_add ( b , WIDGET( wid1 ), TRUE, 0 );
        // Widget not enabled.  no width allocated.
        TASSERTE ( wid1->h, 0);
        TASSERTE ( wid1->w, 0 );
        widget_enable ( WIDGET ( wid1 ) );
        widget_update ( WIDGET ( b ) ) ;
        // Widget enabled.  so width allocated.
        TASSERTE ( wid1->h, 20);
        TASSERTE ( wid1->w, 100 );
        widget *wid2 = g_malloc0(sizeof(widget));
        widget_enable ( WIDGET ( wid2 ) );
        box_add ( b , WIDGET( wid2 ), TRUE, 1 );
        TASSERTE ( wid1->h, 20);
        TASSERTE ( wid1->w, 49);
        TASSERTE ( wid2->h, 20);
        TASSERTE ( wid2->w, 49);

        widget *wid3 = g_malloc0(sizeof(widget));
        widget_enable ( WIDGET ( wid3 ) );
        box_add ( b , WIDGET( wid3 ), FALSE, 2 );
        TASSERTE ( wid1->h, 20);
        TASSERTE ( wid1->w, 48);
        TASSERTE ( wid2->h, 20);
        TASSERTE ( wid2->w, 48);

        widget_resize ( WIDGET (wid3) , 20, 10 );
        // TODO should this happen automagically?
        widget_update ( WIDGET ( b ) ) ;
        TASSERTE ( wid1->h, 20);
        TASSERTE ( wid1->w, 38);
        TASSERTE ( wid2->h, 20);
        TASSERTE ( wid2->w, 38);
        TASSERTE ( wid3->h, 20);
        TASSERTE ( wid3->w, 20);

        widget_resize ( WIDGET (b ), 200, 20 );
        TASSERTE ( wid1->h, 20);
        TASSERTE ( wid1->w, 88);
        TASSERTE ( wid2->h, 20);
        TASSERTE ( wid2->w, 88);
        TASSERTE ( wid3->h, 20);
        TASSERTE ( wid3->w, 20);
//        TASSERTE ( box_get_fixed_pixels ( b ) , 24 );

        widget *wid4 = g_malloc0(sizeof(widget));
        widget_enable ( WIDGET ( wid4 ) );
        widget_resize ( WIDGET ( wid4 ), 20, 20 );
        box_add ( b , WIDGET( wid4 ), FALSE, 5 );
        TASSERTE ( wid4->x, 200-20);
        widget *wid5 = g_malloc0(sizeof(widget));
        widget_enable ( WIDGET ( wid5 ) );
        widget_resize ( WIDGET ( wid5 ), 20, 20 );
        box_add ( b , WIDGET( wid5 ), TRUE, 6 );
        TASSERTE ( wid5->x, 149);
        widget_free ( WIDGET ( b ) );
    }
    {
        box *b = box_create ( "box", BOX_VERTICAL );
        widget_resize ( WIDGET (b), 20, 100);
        //box_set_padding ( b, 5 );

        widget *wid1 = g_malloc0(sizeof(widget));
        box_add ( b , WIDGET( wid1 ), TRUE, 0 );
        // Widget not enabled.  no width allocated.
        TASSERTE ( wid1->h, 0);
        TASSERTE ( wid1->w, 0 );
        widget_enable ( WIDGET ( wid1 ) );
        widget_update ( WIDGET ( b ) ) ;
        // Widget enabled.  so width allocated.
        TASSERTE ( wid1->h, 100);
        TASSERTE ( wid1->w, 20 );
        widget *wid2 = g_malloc0(sizeof(widget));
        widget_enable ( WIDGET ( wid2 ) );
        box_add ( b , WIDGET( wid2 ), TRUE, 1 );
        TASSERTE ( wid1->w, 20);
        TASSERTE ( wid1->h, 49);
        TASSERTE ( wid2->w, 20);
        TASSERTE ( wid2->h, 49);

        widget *wid3 = g_malloc0(sizeof(widget));
        widget_enable ( WIDGET ( wid3 ) );
        box_add ( b , WIDGET( wid3 ), FALSE, 2 );
        TASSERTE ( wid1->w, 20);
        TASSERTE ( wid1->h, 48);
        TASSERTE ( wid2->w, 20);
        TASSERTE ( wid2->h, 48);

        widget_resize ( WIDGET (wid3) , 10, 20 );
        // TODO should this happen automagically?
        widget_update ( WIDGET ( b ) ) ;
        TASSERTE ( wid1->w, 20);
        TASSERTE ( wid1->h, 48);
        TASSERTE ( wid2->w, 20);
        TASSERTE ( wid2->h, 48);
        TASSERTE ( wid3->w, 20);
        TASSERTE ( wid3->h, 0);

        widget_resize ( WIDGET (b ), 20, 200 );
        TASSERTE ( wid1->w, 20);
        TASSERTE ( wid1->h, 98);
        TASSERTE ( wid2->w, 20);
        TASSERTE ( wid2->h, 98);
        TASSERTE ( wid3->w, 20);
        // has no height, gets no height.
        TASSERTE ( wid3->h, 0);
//        TASSERTE ( box_get_fixed_pixels ( b ) , 4 );
        widget *wid4 = g_malloc0(sizeof(widget));
        widget_enable ( WIDGET ( wid4 ) );
        widget_resize ( WIDGET ( wid4 ), 20, 20 );
        box_add ( b , WIDGET( wid4 ), FALSE, 5 );
        TASSERTE ( wid4->y, 200);
        widget *wid5 = g_malloc0(sizeof(widget));
        widget_enable ( WIDGET ( wid5 ) );
        widget_resize ( WIDGET ( wid5 ), 20, 20 );
        box_add ( b , WIDGET( wid5 ), TRUE, 6 );
        TASSERTE ( wid5->y, 136);
        widget_free ( WIDGET ( b ) );
    }
    {
        box *b = box_create ( "box", BOX_VERTICAL );
        widget_resize ( WIDGET (b), 20, 100);
        //box_set_padding ( b, 5 );
        widget *wid1 = g_malloc0(sizeof(widget));
        widget_enable(wid1);
        wid1->clicked = test_widget_clicked;
        box_add ( b , WIDGET( wid1 ), TRUE, 0 );
        widget *wid2 = g_malloc0(sizeof(widget));
        widget_enable(wid2);
        box_add ( b , WIDGET( wid2 ), TRUE, 1 );

        xcb_button_press_event_t xce;
        xce.event_x = 10;
        xce.event_y = 60;
        TASSERTE ( widget_clicked ( WIDGET(b), &xce ), 0);

        xce.event_y = 50;
        TASSERTE ( widget_clicked ( WIDGET(b), &xce ), 0);
        xce.event_y = 48;
        TASSERTE ( widget_clicked ( WIDGET(b), &xce ), 1);
        widget_disable ( wid2 );
        xce.event_y = 60;
        TASSERTE ( widget_clicked ( WIDGET(b), &xce ), 1);
        widget_disable ( wid1 );
        widget_enable ( wid2 );
        TASSERTE ( widget_clicked ( WIDGET(b), &xce ), 0);
        widget_free ( WIDGET ( b ) );
    }
}
Пример #28
0
void Save_Widget::set(Image_Io_Base * in)
{
    _plugin = in;

    widget_update();
}
Пример #29
0
void*
widget_main (struct widget *widget) {
	unsigned short i;
	int xcb_fd;
	int screen_nbr = 0;
	xcb_connection_t *conn = xcb_connect(NULL, NULL);
	xcb_ewmh_connection_t *ewmh = malloc(sizeof(xcb_ewmh_connection_t));
	struct epoll_event xcb_event;

	widget_epoll_init(widget);

	if (xcb_connection_has_error(conn)) {
		LOG_ERR("could not connect to display %s", getenv("DISPLAY"));
		goto cleanup;
	}

	xcb_intern_atom_cookie_t *ewmh_cookie = xcb_ewmh_init_atoms(conn, ewmh);
	xcb_ewmh_init_atoms_replies(ewmh, ewmh_cookie, NULL);

	uint32_t values[] = { XCB_EVENT_MASK_PROPERTY_CHANGE };
	xcb_generic_event_t *evt;
	xcb_generic_error_t *err = xcb_request_check(ewmh->connection,
	                                             xcb_change_window_attributes_checked(ewmh->connection,
	                                                                                  ewmh->screens[screen_nbr]->root,
	                                                                                  XCB_CW_EVENT_MASK,
	                                                                                  values));

	if (err != NULL) {
		LOG_ERR("could not request EWMH property change notifications");
		goto cleanup;
	}

	xcb_fd = xcb_get_file_descriptor(ewmh->connection);
	xcb_event.data.fd = xcb_fd;
	xcb_event.events = EPOLLIN | EPOLLET;
	if (epoll_ctl(efd, EPOLL_CTL_ADD, xcb_fd, &xcb_event) == -1) {
		LOG_ERR("failed to add fd to epoll instance: %s", strerror(errno));

		return 0;
	}

	widget_update(widget, ewmh, screen_nbr);
	while (true) {
		while ((nfds = epoll_wait(efd, events, MAX_EVENTS, -1)) > 0) {
			for (i = 0; i < nfds; i++) {
				if (events[i].data.fd == widget->bar->efd) {
					goto cleanup;
				}
			}

			while ((evt = xcb_poll_for_event(ewmh->connection)) != NULL) {
				xcb_property_notify_event_t *pne;
				switch (XCB_EVENT_RESPONSE_TYPE(evt)) {
				case XCB_PROPERTY_NOTIFY:
					pne = (xcb_property_notify_event_t*)evt;
					if (pne->atom == ewmh->_NET_DESKTOP_NAMES) {
						widget_update(widget, ewmh, screen_nbr);
					}
					else if (pne->atom == ewmh->_NET_NUMBER_OF_DESKTOPS) {
						widget_update(widget, ewmh, screen_nbr);
					}
					else if (pne->atom == ewmh->_NET_CURRENT_DESKTOP) {
						widget_update(widget, ewmh, screen_nbr);
					}
				default:
					break;
				}
				free(evt);
			}
		}
	}

cleanup:
	if (ewmh != NULL) {
		xcb_ewmh_connection_wipe(ewmh);
	}
	if (conn != NULL) {
		xcb_disconnect(conn);
	}

	widget_epoll_cleanup(widget);
	widget_clean_exit(widget);
}
Пример #30
0
static int
widget_update (struct widget *widget, struct widget_config config) {
	CURL *curl;
	CURLcode status;
	char *data;
	long code;

	/* connect and handle IMAP responses */
	curl = curl_easy_init();
	data = malloc(CURL_BUF_SIZE);
	if (!curl || !data) {
		return 0;
	}

	write_result_t write_result = {
		.data = data,
		.pos = 0
	};

	curl_easy_setopt(curl, CURLOPT_USERNAME, config.username);
	curl_easy_setopt(curl, CURLOPT_PASSWORD, config.password);
	curl_easy_setopt(curl, CURLOPT_URL, config.address);
	curl_easy_setopt(curl, CURLOPT_CUSTOMREQUEST, "SEARCH UNSEEN");

	curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, candybar_curl_write_response);
	curl_easy_setopt(curl, CURLOPT_WRITEDATA, &write_result);

	if (config.ssl_verify) {
		curl_easy_setopt(curl, CURLOPT_SSL_VERIFYPEER, 0L);
		curl_easy_setopt(curl, CURLOPT_SSL_VERIFYHOST, 0L);
	}

	status = curl_easy_perform(curl);
	if (status != CURLE_OK) {
		LOG_ERR("unable to request data from %s (this error may be temporary): %s",
		        config.address,
		        curl_easy_strerror(status));

		return 0;
	}

	curl_easy_getinfo(curl, CURLINFO_RESPONSE_CODE, &code);

	if (code != 0) {
		LOG_ERR("server responded with code %ld", code);

		return 0;
	}

	curl_easy_cleanup(curl);
	curl_global_cleanup();

	data[write_result.pos] = '\0';

	/* count unread message IDs */

	/* the server responds with a string like "* SEARCH 1 2 3 4" where the
	   numbers are message IDs */
	char *str, *saveptr, *delim = " *";
	int unread = -1;

	str = strtok_r(data, delim, &saveptr);
	while (str != NULL) {
		str = strtok_r(NULL, delim, &saveptr);
		unread++;
	}

	free(data);

	widget_data_callback(widget,
	                     widget_data_arg_number(unread),
	                     widget_data_arg_string(config.username));

	return 0;
}

static const char*
next (const char *ch, int space) {
	while (*ch && !isspace(*ch) == !space) {
		++ch;
	}

	return ch;
}

static int
parse_cmdline_arguments (const char *password_command, struct Process *proc) {
	const char *start = next(password_command, 1);
	if (!*start) {
		return -1;
	}
	const char *end = next(start, 0);
	if (!*end) {
		proc->path = strdup(start);
	}
	else {
		proc->path = strndup(start, end - start);
	}
	proc->argv = calloc(1024, sizeof(char*));
	proc->argv[0] = proc->path;
	int argv_idx = 1;

	while ((start = next(end, 1))) {
		end = next(start, 0);
		if (!*end) {
			proc->argv[argv_idx++] = strdup(start);
			break;
		}
		else {
			proc->argv[argv_idx++] = strndup(start, end - start);
		}
	}

	return 1;
}

void*
widget_main (struct widget *widget) {
	struct widget_config config = widget_config_defaults;
	widget_init_config_string(widget->config, "address", config.address);
	widget_init_config_string(widget->config, "username", config.username);
	widget_init_config_string(widget->config, "password", config.password);
	widget_init_config_string(widget->config, "password_command", config.password_command);
	widget_init_config_boolean(widget->config, "ssl_verify", config.ssl_verify);
	widget_init_config_integer(widget->config, "refresh_interval", config.refresh_interval);

	if (!config.username) {
		LOG_INFO("email_imap: username not set, disabling widget");

		return 0;
	}

	struct Buffer buffer;
	memset(&buffer, 0, sizeof(buffer));
	if (strlen(config.password_command)) {
		struct Process proc;
		memset(&proc, 0, sizeof(proc));
		proc.stderr_cb = write_stderr;
		proc.stdout_cb = write_stdout;
		proc.user_data = &buffer;
		if (parse_cmdline_arguments(config.password_command, &proc) == -1) {
			LOG_ERR("email_imap: cannot parse password_command: \"%s\"", config.password_command);

			return 0;
		}

		const int ret = process(&proc);
		free_process(&proc);
		if (ret != 0) {
			LOG_ERR("email_imap: process error: %s => %d: %s/%s\n", proc.path, ret, proc.error, buffer.stderr_buffer);

			return 0;
		}
		config.password = buffer.stdout_buffer;
	}

	widget_epoll_init(widget);
	while (true) {
		widget_update(widget, config);
		widget_epoll_wait_goto(widget, config.refresh_interval, cleanup);
	}

cleanup:

	widget_epoll_cleanup(widget);
	widget_clean_exit(widget);
	free_buffer(&buffer);
}