From d30f9b83e681e72ce1ee54de3ac81088fb0bdf9b Mon Sep 17 00:00:00 2001 From: Ashwin Rajesh <46510831+VanillaViking@users.noreply.github.com> Date: Mon, 11 Sep 2023 19:07:46 +1000 Subject: [PATCH] Add functionality to draw lines via command * action: add a --line command line option for drawing lines * targets: add GA_LINE and GA_LINEDATA targets to allow cli to send parameters to the main app * chore: remove debug logs * chore: formatting fixes * callbacks: free line_ctx, might prevent potential memory leak * README: add docs for --line command * callbacks: fix memory leak * main: indentation fixes * cmdline: failsafe checks * cmdline: fix minor failsafe check bug * README: add line example * README: indentation error * README: add quotes around color argument --- README.md | 3 +++ src/callbacks.c | 63 ++++++++++++++++++++++++++++++++++++++++++++++++- src/main.c | 36 ++++++++++++++++++++++++++++ src/main.h | 2 ++ 4 files changed, 103 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 0a9b846..0b76119 100644 --- a/README.md +++ b/README.md @@ -96,6 +96,9 @@ Usage: will undo the last drawing stroke (or "-z") gromit-mpx --redo will redo the last undone drawing stroke (or "-y") + gromit-mpx --line + will draw a straight line with characteristics specified by the arguments (or "-l") + eg: gromit-mpx -l 200 200 400 400 '#C4A7E7' 6 If activated Gromit-MPX prevents you from using other programs with the mouse. You can press the button and paint on the screen. Key presses diff --git a/src/callbacks.c b/src/callbacks.c index 5ea57ce..8099a9c 100644 --- a/src/callbacks.c +++ b/src/callbacks.c @@ -205,7 +205,8 @@ void on_clientapp_selection_get (GtkWidget *widget, if(data->debug) g_printerr("DEBUG: clientapp received request.\n"); - if (gtk_selection_data_get_target(selection_data) == GA_TOGGLEDATA) + + if (gtk_selection_data_get_target(selection_data) == GA_TOGGLEDATA || gtk_selection_data_get_target(selection_data) == GA_LINEDATA) { ans = data->clientdata; } @@ -435,6 +436,13 @@ void on_mainapp_selection_get (GtkWidget *widget, GA_TOGGLEDATA, time); gtk_main(); /* Wait for the response */ } + else if(action == GA_LINE) + { + /* ask back client for device id */ + gtk_selection_convert (data->win, GA_DATA, + GA_LINEDATA, time); + gtk_main(); /* Wait for the response */ + } else if (action == GA_VISIBILITY) toggle_visibility (data); else if (action == GA_CLEAR) @@ -502,6 +510,59 @@ void on_mainapp_selection_received (GtkWidget *widget, g_printerr("ERROR: No device at index %ld.\n", (long)dev_nr); } } + else if (gtk_selection_data_get_target(selection_data) == GA_LINEDATA) + { + + gchar** line_args = g_strsplit((gchar*)gtk_selection_data_get_data(selection_data), " ", 6); + int startX = atoi(line_args[0]); + int startY = atoi(line_args[1]); + int endX = atoi(line_args[2]); + int endY = atoi(line_args[3]); + gchar* hex_code = line_args[4]; + int thickness = atoi(line_args[5]); + + if(data->debug) + { + g_printerr("DEBUG: mainapp got line data back from client:\n"); + g_printerr("startX startY endX endY: %d %d %d %d\n", startX, startY, endX, endY); + g_printerr("color: %s\n", hex_code); + g_printerr("thickness: %d\n", thickness); + } + + GdkRGBA* color = g_malloc (sizeof (GdkRGBA)); + GdkRGBA *fg_color=data->red; + if (gdk_rgba_parse (color, hex_code)) + { + fg_color = color; + } + else + { + g_printerr ("Unable to parse color. " + "Keeping default.\n"); + } + GromitPaintContext* line_ctx = paint_context_new(data, GROMIT_PEN, fg_color, thickness, 0, thickness, thickness); + + GdkRectangle rect; + rect.x = MIN (startX,endX) - thickness / 2; + rect.y = MIN (startY,endY) - thickness / 2; + rect.width = ABS (startX-endX) + thickness; + rect.height = ABS (startY-endY) + thickness; + + if(data->debug) + g_printerr("DEBUG: draw line from %d %d to %d %d\n", startX, startY, endX, endY); + + cairo_set_line_width(line_ctx->paint_ctx, thickness); + cairo_move_to(line_ctx->paint_ctx, startX, startY); + cairo_line_to(line_ctx->paint_ctx, endX, endY); + cairo_stroke(line_ctx->paint_ctx); + + data->modified = 1; + gdk_window_invalidate_rect(gtk_widget_get_window(data->win), &rect, 0); + data->painted = 1; + + g_free(line_ctx); + g_free (color); + } } gtk_main_quit (); diff --git a/src/main.c b/src/main.c index 8366a45..20f4454 100644 --- a/src/main.c +++ b/src/main.c @@ -653,6 +653,7 @@ void setup_main_app (GromitData *data, int argc, char ** argv) gtk_selection_add_target (data->win, GA_CONTROL, GA_RELOAD, 7); gtk_selection_add_target (data->win, GA_CONTROL, GA_UNDO, 8); gtk_selection_add_target (data->win, GA_CONTROL, GA_REDO, 9); + gtk_selection_add_target (data->win, GA_CONTROL, GA_LINE, 10); @@ -982,6 +983,40 @@ int main_client (int argc, char **argv, GromitData *data) else data->clientdata = "-1"; /* default to grab all */ } + else if (strcmp (arg, "-l") == 0 || + strcmp (arg, "--line") == 0) + { + if (argc - (i+1) == 6) /* this command must have exactly 6 params */ + { + + // check if provided values are valid coords on the screen + if (atoi(argv[i+1]) < 0 || atoi(argv[i+1]) > (int)data->width || + atoi(argv[i+2]) < 0 || atoi(argv[i+2]) > (int)data->height || + atoi(argv[i+3]) < 0 || atoi(argv[i+3]) > (int)data->width || + atoi(argv[i+4]) < 0 || atoi(argv[i+4]) > (int)data->height) + { + g_printerr ("Invalid coordinates\n"); + wrong_arg = TRUE; + } + else if (atoi(argv[i+6]) < 1) + { + g_printerr ("Thickness must be atleast 1\n"); + wrong_arg = TRUE; + } + else + { + data->clientdata = g_strjoin(" ", argv[i+1], argv[i+2], argv[i+3], argv[i+4], argv[i+5], argv[i+6], NULL); + } + + action = GA_LINE; + i += 6; + } + else + { + g_printerr ("-l requires 6 parameters: startX, startY, endX, endY, color, thickness\n"); + wrong_arg = TRUE; + } + } else if (strcmp (arg, "-v") == 0 || strcmp (arg, "--visibility") == 0) { @@ -1093,6 +1128,7 @@ int main (int argc, char **argv) gtk_selection_owner_set (data->win, GA_DATA, GDK_CURRENT_TIME); gtk_selection_add_target (data->win, GA_DATA, GA_TOGGLEDATA, 1007); + gtk_selection_add_target (data->win, GA_DATA, GA_LINEDATA, 1008); diff --git a/src/main.h b/src/main.h index 2803139..ae89970 100644 --- a/src/main.h +++ b/src/main.h @@ -48,6 +48,7 @@ #define GA_ACTIVATE gdk_atom_intern ("Gromit/activate", FALSE) #define GA_DEACTIVATE gdk_atom_intern ("Gromit/deactivate", FALSE) #define GA_TOGGLE gdk_atom_intern ("Gromit/toggle", FALSE) +#define GA_LINE gdk_atom_intern ("Gromit/line", FALSE) #define GA_VISIBILITY gdk_atom_intern ("Gromit/visibility", FALSE) #define GA_CLEAR gdk_atom_intern ("Gromit/clear", FALSE) #define GA_RELOAD gdk_atom_intern ("Gromit/reload", FALSE) @@ -56,6 +57,7 @@ #define GA_DATA gdk_atom_intern ("Gromit/data", FALSE) #define GA_TOGGLEDATA gdk_atom_intern ("Gromit/toggledata", FALSE) +#define GA_LINEDATA gdk_atom_intern ("Gromit/linedata", FALSE) #define GROMIT_MAX_UNDO 4