Commit ffd69794 authored by Victor Ananjevsky's avatar Victor Ananjevsky

add color picker to color dialog and yad-tools

parent 14f695ff
...@@ -346,6 +346,9 @@ Set initial color value. ...@@ -346,6 +346,9 @@ Set initial color value.
.B \-\-gtk-palette .B \-\-gtk-palette
Show system palette inside color dialog. For GTK+3 builds this option shows palette instead of color editor. Show system palette inside color dialog. For GTK+3 builds this option shows palette instead of color editor.
.TP .TP
.B \-\-picker
Add screen color picker button.
.TP
.B \-\-alpha .B \-\-alpha
Add opacity to output color string. Add opacity to output color string.
.TP .TP
......
...@@ -6,6 +6,8 @@ if !STANDALONE ...@@ -6,6 +6,8 @@ if !STANDALONE
bin_SCRIPTS = yad-settings bin_SCRIPTS = yad-settings
endif endif
CPICKER_SOURCES = cpicker.c cpicker.h
yad_SOURCES = \ yad_SOURCES = \
about.c \ about.c \
app.c \ app.c \
...@@ -29,7 +31,8 @@ yad_SOURCES = \ ...@@ -29,7 +31,8 @@ yad_SOURCES = \
util.c \ util.c \
main.c \ main.c \
yad.h \ yad.h \
calendar.xpm calendar.xpm \
$(CPICKER_SOURCES)
if TRAY if TRAY
yad_SOURCES += notification.c yad_SOURCES += notification.c
...@@ -49,7 +52,7 @@ yad_LDADD = $(GTK_LIBS) $(HTML_LIBS) $(SPELL_LIBS) $(SOURCEVIEW_LIBS) ...@@ -49,7 +52,7 @@ yad_LDADD = $(GTK_LIBS) $(HTML_LIBS) $(SPELL_LIBS) $(SOURCEVIEW_LIBS)
if BUILD_TOOLS if BUILD_TOOLS
bin_PROGRAMS += yad-tools bin_PROGRAMS += yad-tools
yad_tools_SOURCES = tools.c yad_tools_SOURCES = tools.c $(CPICKER_SOURCES)
yad_tools_CFLAGS = $(GTK_CFLAGS) $(SPELL_CFLAGS) $(SOURCEVIEW_CFLAGS) yad_tools_CFLAGS = $(GTK_CFLAGS) $(SPELL_CFLAGS) $(SOURCEVIEW_CFLAGS)
yad_tools_LDADD = $(GTK_LIBS) $(SPELL_LIBS) $(SOURCEVIEW_LIBS) yad_tools_LDADD = $(GTK_LIBS) $(SPELL_LIBS) $(SOURCEVIEW_LIBS)
endif endif
......
...@@ -20,6 +20,7 @@ ...@@ -20,6 +20,7 @@
#include <errno.h> #include <errno.h>
#include "yad.h" #include "yad.h"
#include "cpicker.h"
static GtkWidget *color; static GtkWidget *color;
...@@ -102,6 +103,12 @@ set_color (gchar *clr) ...@@ -102,6 +103,12 @@ set_color (gchar *clr)
} }
static void static void
picker_clicked (GtkWidget *w, gpointer data)
{
yad_get_screen_color (color);
}
static void
palette_changed (GtkTreeSelection * sel, gpointer data) palette_changed (GtkTreeSelection * sel, gpointer data)
{ {
GtkTreeModel *model; GtkTreeModel *model;
...@@ -129,6 +136,21 @@ color_create_widget (GtkWidget * dlg) ...@@ -129,6 +136,21 @@ color_create_widget (GtkWidget * dlg)
set_color (options.color_data.init_color); set_color (options.color_data.init_color);
gtk_box_pack_start (GTK_BOX (w), color, FALSE, FALSE, 2); gtk_box_pack_start (GTK_BOX (w), color, FALSE, FALSE, 2);
if (options.color_data.color_picker)
{
GtkWidget *b, *i;
b = gtk_button_new_with_label (_("Pick up screen color"));
i = gtk_image_new_from_icon_name ("gtk-color-picker", GTK_ICON_SIZE_BUTTON);
gtk_button_set_image (GTK_BUTTON (b), i);
g_object_set (G_OBJECT (b), "always-show-image", TRUE, NULL);
g_signal_connect (G_OBJECT (b), "clicked", G_CALLBACK (picker_clicked), NULL);
gtk_box_pack_start (GTK_BOX (w), b, FALSE, FALSE, 2);
}
if (options.color_data.use_palette) if (options.color_data.use_palette)
{ {
GtkTreeModel *model; GtkTreeModel *model;
......
/*
* This file is part of YAD.
*
* YAD 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 3 of the License, or
* (at your option) any later version.
*
* YAD 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 YAD. If not, see <http://www.gnu.org/licenses/>.
*
* Copyright (C) 2020-2022, Victor Ananjevsky <ananasik@gmail.com>
*/
/* This code getted from deprecated GtkColorSelection widget (gtk+-3.24.33) */
#define GDK_DISABLE_DEPRECATION_WARNINGS
#include "cpicker.h"
#define BIG_STEP 20
typedef struct {
GtkWidget *color_widget;
GtkWidget *grab_widget;
GdkDevice *keyb_device;
GdkDevice *pointer_device;
gboolean has_grab;
guint32 time;
} GrabData;
static GdkRGBA selected_color; /* selected color */
static gboolean pickup_made = FALSE; /* true when color was picked up */
static gboolean pickup_done = FALSE; /* true when pickup was made or canceled */
static gboolean key_press (GtkWidget * invisible, GdkEventKey * event, gpointer data);
static gboolean mouse_press (GtkWidget * invisible, GdkEventButton * event, gpointer data);
static GdkCursor *
make_picker_cursor (GdkScreen * screen)
{
GdkDisplay *display;
GdkCursor *cursor;
display = gdk_screen_get_display (screen);
cursor = gdk_cursor_new_from_name (display, "color-picker");
if (!cursor)
cursor = gdk_cursor_new_from_name (display, "cell");
if (!cursor)
g_printerr ("cpicker: cannot create cursor\n");
return cursor;
}
static void
grab_color_at_pointer (GdkScreen * screen, GdkDevice * device, gint x_root, gint y_root, gpointer data)
{
GdkPixbuf *pixbuf;
guchar *pixels;
GdkRGBA color;
GdkWindow *root_window = gdk_screen_get_root_window (screen);
GrabData *gd = (GrabData *) data;
pixbuf = gdk_pixbuf_get_from_window (root_window, x_root, y_root, 1, 1);
if (!pixbuf)
{
gint x, y;
GdkWindow *window = gdk_device_get_window_at_position (device, &x, &y);
if (!window)
return;
pixbuf = gdk_pixbuf_get_from_window (window, x, y, 1, 1);
if (!pixbuf)
return;
}
pixels = gdk_pixbuf_get_pixels (pixbuf);
color.red = pixels[0] / 255.;
color.green = pixels[1] / 255.;
color.blue = pixels[2] / 255.;
color.alpha = 1.0;
g_object_unref (pixbuf);
if (gd->color_widget)
gtk_color_chooser_set_rgba (GTK_COLOR_CHOOSER (gd->color_widget), &color);
else
g_print ("#%02X%02X%02X\n", (gint) (color.red * 255), (gint) (color.green * 255), (gint) (color.blue * 255));
}
static void
shutdown_eyedropper (gpointer data)
{
GrabData *gd = (GrabData *) data;
if (gd->has_grab)
{
gdk_device_ungrab (gd->keyb_device, gd->time);
gdk_device_ungrab (gd->pointer_device, gd->time);
gtk_device_grab_remove (gd->grab_widget, gd->pointer_device);
}
if (gd->color_widget == NULL)
gtk_main_quit ();
}
static void
mouse_motion (GtkWidget * invisible, GdkEventMotion * event, gpointer data)
{
grab_color_at_pointer (gdk_event_get_screen ((GdkEvent *) event),
gdk_event_get_device ((GdkEvent *) event), event->x_root, event->y_root, data);
}
static gboolean
mouse_release (GtkWidget * invisible, GdkEventButton * event, gpointer data)
{
/* GtkColorSelection *colorsel = data; */
if (event->button != GDK_BUTTON_PRIMARY)
return FALSE;
grab_color_at_pointer (gdk_event_get_screen ((GdkEvent *) event),
gdk_event_get_device ((GdkEvent *) event), event->x_root, event->y_root, data);
shutdown_eyedropper (data);
g_signal_handlers_disconnect_by_func (invisible, mouse_motion, data);
g_signal_handlers_disconnect_by_func (invisible, mouse_release, data);
return TRUE;
}
/* Helper Functions */
static gboolean
key_press (GtkWidget * invisible, GdkEventKey * event, gpointer data)
{
GdkScreen *screen = gdk_event_get_screen ((GdkEvent *) event);
GdkDevice *device, *pointer_device;
guint state = event->state & gtk_accelerator_get_default_mod_mask ();
gint x, y, dx, dy;
device = gdk_event_get_device ((GdkEvent *) event);
pointer_device = gdk_device_get_associated_device (device);
gdk_device_get_position (pointer_device, NULL, &x, &y);
dx = dy = 0;
switch (event->keyval)
{
case GDK_KEY_space:
case GDK_KEY_Return:
case GDK_KEY_ISO_Enter:
case GDK_KEY_KP_Enter:
case GDK_KEY_KP_Space:
grab_color_at_pointer (screen, pointer_device, x, y, data);
/* fall through */
case GDK_KEY_Escape:
shutdown_eyedropper (data);
g_signal_handlers_disconnect_by_func (invisible, mouse_press, data);
g_signal_handlers_disconnect_by_func (invisible, key_press, data);
return TRUE;
case GDK_KEY_Up:
case GDK_KEY_KP_Up:
dy = state == GDK_MOD1_MASK ? -BIG_STEP : -1;
break;
case GDK_KEY_Down:
case GDK_KEY_KP_Down:
dy = state == GDK_MOD1_MASK ? BIG_STEP : 1;
break;
case GDK_KEY_Left:
case GDK_KEY_KP_Left:
dx = state == GDK_MOD1_MASK ? -BIG_STEP : -1;
break;
case GDK_KEY_Right:
case GDK_KEY_KP_Right:
dx = state == GDK_MOD1_MASK ? BIG_STEP : 1;
break;
default:
return FALSE;
}
gdk_device_warp (pointer_device, screen, x + dx, y + dy);
return TRUE;
}
static gboolean
mouse_press (GtkWidget * invisible, GdkEventButton * event, gpointer data)
{
if (event->type == GDK_BUTTON_PRESS && event->button == GDK_BUTTON_PRIMARY)
{
g_signal_connect (invisible, "motion-notify-event", G_CALLBACK (mouse_motion), data);
g_signal_connect (invisible, "button-release-event", G_CALLBACK (mouse_release), data);
g_signal_handlers_disconnect_by_func (invisible, mouse_press, data);
g_signal_handlers_disconnect_by_func (invisible, key_press, data);
return TRUE;
}
return FALSE;
}
void
yad_get_screen_color (GtkWidget *widget)
{
GrabData *gd;
GdkScreen *screen;
GdkDevice *device;
GdkCursor *picker_cursor;
GdkGrabStatus grab_status;
GdkWindow *window;
gd = g_new0 (GrabData, 1);
gd->color_widget = widget;
gd->time = gtk_get_current_event_time ();
screen = gdk_screen_get_default ();
device = gtk_get_current_event_device ();
if (device)
{
if (gdk_device_get_source (device) == GDK_SOURCE_KEYBOARD)
{
gd->keyb_device = device;
gd->pointer_device = gdk_device_get_associated_device (device);
}
else
{
gd->pointer_device = device;
gd->keyb_device = gdk_device_get_associated_device (device);
}
}
else
{
GdkSeat *seat = gdk_display_get_default_seat (gdk_screen_get_display (screen));
gd->keyb_device = gdk_seat_get_keyboard (seat);
gd->pointer_device = gdk_seat_get_pointer (seat);
}
gd->grab_widget = gtk_window_new (GTK_WINDOW_POPUP);
gtk_window_set_screen (GTK_WINDOW (gd->grab_widget), screen);
gtk_window_resize (GTK_WINDOW (gd->grab_widget), 1, 1);
gtk_window_move (GTK_WINDOW (gd->grab_widget), -100, -100);
gtk_widget_show (gd->grab_widget);
gtk_widget_add_events (gd->grab_widget, GDK_BUTTON_RELEASE_MASK | GDK_BUTTON_PRESS_MASK | GDK_POINTER_MOTION_MASK);
window = gtk_widget_get_window (gd->grab_widget);
if (gdk_device_grab (gd->keyb_device, window, GDK_OWNERSHIP_APPLICATION, FALSE,
GDK_KEY_PRESS_MASK | GDK_KEY_RELEASE_MASK, NULL, gd->time) != GDK_GRAB_SUCCESS)
return;
picker_cursor = make_picker_cursor (screen);
grab_status = gdk_device_grab (gd->pointer_device, window, GDK_OWNERSHIP_APPLICATION, FALSE,
GDK_BUTTON_RELEASE_MASK | GDK_BUTTON_PRESS_MASK | GDK_POINTER_MOTION_MASK,
picker_cursor, gd->time);
if (picker_cursor)
g_object_unref (picker_cursor);
if (grab_status != GDK_GRAB_SUCCESS)
{
gdk_device_ungrab (gd->keyb_device, gd->time);
return;
}
gtk_device_grab_add (gd->grab_widget, gd->pointer_device, TRUE);
gd->has_grab = TRUE;
g_signal_connect (gd->grab_widget, "button-press-event", G_CALLBACK (mouse_press), gd);
g_signal_connect (gd->grab_widget, "key-press-event", G_CALLBACK (key_press), gd);
}
#ifndef __CPICKER_H__
#define __CPICKER_H__
#include <gtk/gtk.h>
void yad_get_screen_color (GtkWidget *widget);
#endif /* __CPICKER_H__ */
...@@ -309,6 +309,8 @@ static GOptionEntry color_options[] = { ...@@ -309,6 +309,8 @@ static GOptionEntry color_options[] = {
N_("Set path to palette file. Default - " RGB_FILE), N_("[FILENAME]") }, N_("Set path to palette file. Default - " RGB_FILE), N_("[FILENAME]") },
{ "expand-palette", 0, 0, G_OPTION_ARG_NONE, &options.color_data.expand_palette, { "expand-palette", 0, 0, G_OPTION_ARG_NONE, &options.color_data.expand_palette,
N_("Expand user palette"), NULL }, N_("Expand user palette"), NULL },
{ "picker", 0, 0, G_OPTION_ARG_NONE, &options.color_data.color_picker,
N_("Show color picker"), NULL },
{ "mode", 0, 0, G_OPTION_ARG_CALLBACK, set_color_mode, { "mode", 0, 0, G_OPTION_ARG_CALLBACK, set_color_mode,
N_("Set output mode to MODE. Values are hex (default) or rgb"), N_("MODE") }, N_("Set output mode to MODE. Values are hex (default) or rgb"), N_("MODE") },
{ "alpha", 0, 0, G_OPTION_ARG_NONE, &options.color_data.alpha, { "alpha", 0, 0, G_OPTION_ARG_NONE, &options.color_data.alpha,
...@@ -1704,6 +1706,7 @@ yad_options_init (void) ...@@ -1704,6 +1706,7 @@ yad_options_init (void)
options.color_data.init_color = NULL; options.color_data.init_color = NULL;
options.color_data.gtk_palette = FALSE; options.color_data.gtk_palette = FALSE;
options.color_data.use_palette = FALSE; options.color_data.use_palette = FALSE;
options.color_data.color_picker = FALSE;
options.color_data.expand_palette = FALSE; options.color_data.expand_palette = FALSE;
options.color_data.palette = NULL; options.color_data.palette = NULL;
options.color_data.alpha = FALSE; options.color_data.alpha = FALSE;
......
...@@ -30,6 +30,8 @@ ...@@ -30,6 +30,8 @@
#include <gtksourceview/gtksource.h> #include <gtksourceview/gtksource.h>
#endif #endif
#include "cpicker.h"
typedef enum { typedef enum {
PANGO_SPEC, PANGO_SPEC,
XFT_SPEC XFT_SPEC
...@@ -42,6 +44,7 @@ static FontType font_type = XFT_SPEC; ...@@ -42,6 +44,7 @@ static FontType font_type = XFT_SPEC;
static gboolean pfd_mode = FALSE; static gboolean pfd_mode = FALSE;
static gboolean icon_mode = FALSE; static gboolean icon_mode = FALSE;
static gboolean color_mode = FALSE;
static gboolean mime = FALSE; static gboolean mime = FALSE;
static gboolean ver = FALSE; static gboolean ver = FALSE;
#ifdef HAVE_SPELL #ifdef HAVE_SPELL
...@@ -50,6 +53,7 @@ static gboolean langs_mode = FALSE; ...@@ -50,6 +53,7 @@ static gboolean langs_mode = FALSE;
#ifdef HAVE_SOURCEVIEW #ifdef HAVE_SOURCEVIEW
static gboolean themes_mode = FALSE; static gboolean themes_mode = FALSE;
#endif #endif
gboolean pick_color = FALSE;
static guint icon_size = 24; static guint icon_size = 24;
static gchar *icon_theme_name = NULL; static gchar *icon_theme_name = NULL;
...@@ -84,6 +88,12 @@ static GOptionEntry icon_ents[] = { ...@@ -84,6 +88,12 @@ static GOptionEntry icon_ents[] = {
{ NULL } { NULL }
}; };
static GOptionEntry color_ents[] = {
{ "color", 'c', G_OPTION_FLAG_IN_MAIN, G_OPTION_ARG_NONE, &color_mode, N_("Color manipulation tools"), NULL },
{ "pick", 0, 0, G_OPTION_ARG_NONE, &pick_color, N_("Pick up screen color"), NULL },
{ NULL }
};
static gboolean static gboolean
set_font_type (const gchar *name, const gchar *val, gpointer d, GError **err) set_font_type (const gchar *name, const gchar *val, gpointer d, GError **err)
{ {
...@@ -284,7 +294,7 @@ run_icon_mode () ...@@ -284,7 +294,7 @@ run_icon_mode ()
if (mime) if (mime)
{ {
gchar *ctype = g_content_type_from_mime_type (args[0]); gchar *ctype = g_content_type_from_mime_type (args[0]);
output = g_content_type_get_generic_icon_name (ctype); output = g_content_type_get_generic_icon_name (ctype);
} }
else else
{ {
...@@ -293,7 +303,7 @@ run_icon_mode () ...@@ -293,7 +303,7 @@ run_icon_mode ()
return 1; return 1;
output = (gchar *) gtk_icon_info_get_filename (ii); output = (gchar *) gtk_icon_info_get_filename (ii);
} }
if (output) if (output)
g_print ("%s\n", output); g_print ("%s\n", output);
else else
...@@ -302,6 +312,19 @@ run_icon_mode () ...@@ -302,6 +312,19 @@ run_icon_mode ()
return 0; return 0;
} }
static gint
run_color_mode ()
{
if (pick_color)
{
gtk_init (NULL, NULL);
yad_get_screen_color (NULL);
gtk_main ();
}
return 0;
}
#ifdef HAVE_SPELL #ifdef HAVE_SPELL
static gint static gint
show_langs () show_langs ()
...@@ -313,7 +336,7 @@ show_langs () ...@@ -313,7 +336,7 @@ show_langs ()
const GspellLanguage *l = lng->data; const GspellLanguage *l = lng->data;
g_print ("%s\n", gspell_language_get_code (l)); g_print ("%s\n", gspell_language_get_code (l));
} }
return 0; return 0;
} }
#endif #endif
...@@ -336,7 +359,7 @@ show_themes () ...@@ -336,7 +359,7 @@ show_themes ()
g_print ("%s\n", gtk_source_style_scheme_get_name (s)); g_print ("%s\n", gtk_source_style_scheme_get_name (s));
i++; i++;
} }
return 0; return 0;
} }
#endif #endif
...@@ -372,6 +395,11 @@ main (int argc, char *argv[]) ...@@ -372,6 +395,11 @@ main (int argc, char *argv[])
g_option_group_set_translation_domain (grp, GETTEXT_PACKAGE); g_option_group_set_translation_domain (grp, GETTEXT_PACKAGE);
g_option_context_add_group (ctx, grp); g_option_context_add_group (ctx, grp);
grp = g_option_group_new ("color", _("Color mode"), _("Show color mode options"), NULL, NULL);
g_option_group_add_entries (grp, color_ents);
g_option_group_set_translation_domain (grp, GETTEXT_PACKAGE);
g_option_context_add_group (ctx, grp);
if (!g_option_context_parse (ctx, &argc, &argv, &err)) if (!g_option_context_parse (ctx, &argc, &argv, &err))
{ {
g_printerr (_("option parsing failed: %s\n"), err->message); g_printerr (_("option parsing failed: %s\n"), err->message);
...@@ -388,6 +416,8 @@ main (int argc, char *argv[]) ...@@ -388,6 +416,8 @@ main (int argc, char *argv[])
ret = run_pfd_mode (); ret = run_pfd_mode ();
else if (icon_mode) else if (icon_mode)
ret = run_icon_mode (); ret = run_icon_mode ();
else if (color_mode)
ret = run_color_mode ();
#ifdef HAVE_SPELL #ifdef HAVE_SPELL
else if (langs_mode) else if (langs_mode)
ret = show_langs (); ret = show_langs ();
......
...@@ -298,6 +298,7 @@ typedef struct { ...@@ -298,6 +298,7 @@ typedef struct {
gchar *init_color; gchar *init_color;
gboolean gtk_palette; gboolean gtk_palette;
gboolean use_palette; gboolean use_palette;
gboolean color_picker;
gboolean expand_palette; gboolean expand_palette;
gchar *palette; gchar *palette;
gboolean alpha; gboolean alpha;
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment