68#include <gdk/gdkkeysyms.h>
69#include <glib/gstdio.h>
109 pthread_cond_init(&s->
cond, NULL);
145 { GDK_X_CURSOR,
"GDK_X_CURSOR" },
146 { GDK_ARROW,
"GDK_ARROW" },
147 { GDK_BASED_ARROW_DOWN,
"GDK_BASED_ARROW_DOWN" },
148 { GDK_BASED_ARROW_UP,
"GDK_BASED_ARROW_UP" },
149 { GDK_BOAT,
"GDK_BOAT" },
150 { GDK_BOGOSITY,
"GDK_BOGOSITY" },
151 { GDK_BOTTOM_LEFT_CORNER,
"GDK_BOTTOM_LEFT_CORNER" },
152 { GDK_BOTTOM_RIGHT_CORNER,
"GDK_BOTTOM_RIGHT_CORNER" },
153 { GDK_BOTTOM_SIDE,
"GDK_BOTTOM_SIDE" },
154 { GDK_BOTTOM_TEE,
"GDK_BOTTOM_TEE" },
155 { GDK_BOX_SPIRAL,
"GDK_BOX_SPIRAL" },
156 { GDK_CENTER_PTR,
"GDK_CENTER_PTR" },
157 { GDK_CIRCLE,
"GDK_CIRCLE" },
158 { GDK_CLOCK,
"GDK_CLOCK" },
159 { GDK_COFFEE_MUG,
"GDK_COFFEE_MUG" },
160 { GDK_CROSS,
"GDK_CROSS" },
161 { GDK_CROSS_REVERSE,
"GDK_CROSS_REVERSE" },
162 { GDK_CROSSHAIR,
"GDK_CROSSHAIR" },
163 { GDK_DIAMOND_CROSS,
"GDK_DIAMOND_CROSS" },
164 { GDK_DOT,
"GDK_DOT" },
165 { GDK_DOTBOX,
"GDK_DOTBOX" },
166 { GDK_DOUBLE_ARROW,
"GDK_DOUBLE_ARROW" },
167 { GDK_DRAFT_LARGE,
"GDK_DRAFT_LARGE" },
168 { GDK_DRAFT_SMALL,
"GDK_DRAFT_SMALL" },
169 { GDK_DRAPED_BOX,
"GDK_DRAPED_BOX" },
170 { GDK_EXCHANGE,
"GDK_EXCHANGE" },
171 { GDK_FLEUR,
"GDK_FLEUR" },
172 { GDK_GOBBLER,
"GDK_GOBBLER" },
173 { GDK_GUMBY,
"GDK_GUMBY" },
174 { GDK_HAND1,
"GDK_HAND1" },
175 { GDK_HAND2,
"GDK_HAND2" },
176 { GDK_HEART,
"GDK_HEART" },
177 { GDK_ICON,
"GDK_ICON" },
178 { GDK_IRON_CROSS,
"GDK_IRON_CROSS" },
179 { GDK_LEFT_PTR,
"GDK_LEFT_PTR" },
180 { GDK_LEFT_SIDE,
"GDK_LEFT_SIDE" },
181 { GDK_LEFT_TEE,
"GDK_LEFT_TEE" },
182 { GDK_LEFTBUTTON,
"GDK_LEFTBUTTON" },
183 { GDK_LL_ANGLE,
"GDK_LL_ANGLE" },
184 { GDK_LR_ANGLE,
"GDK_LR_ANGLE" },
185 { GDK_MAN,
"GDK_MAN" },
186 { GDK_MIDDLEBUTTON,
"GDK_MIDDLEBUTTON" },
187 { GDK_MOUSE,
"GDK_MOUSE" },
188 { GDK_PENCIL,
"GDK_PENCIL" },
189 { GDK_PIRATE,
"GDK_PIRATE" },
190 { GDK_PLUS,
"GDK_PLUS" },
191 { GDK_QUESTION_ARROW,
"GDK_QUESTION_ARROW" },
192 { GDK_RIGHT_PTR,
"GDK_RIGHT_PTR" },
193 { GDK_RIGHT_SIDE,
"GDK_RIGHT_SIDE" },
194 { GDK_RIGHT_TEE,
"GDK_RIGHT_TEE" },
195 { GDK_RIGHTBUTTON,
"GDK_RIGHTBUTTON" },
196 { GDK_RTL_LOGO,
"GDK_RTL_LOGO" },
197 { GDK_SAILBOAT,
"GDK_SAILBOAT" },
198 { GDK_SB_DOWN_ARROW,
"GDK_SB_DOWN_ARROW" },
199 { GDK_SB_H_DOUBLE_ARROW,
"GDK_SB_H_DOUBLE_ARROW" },
200 { GDK_SB_LEFT_ARROW,
"GDK_SB_LEFT_ARROW" },
201 { GDK_SB_RIGHT_ARROW,
"GDK_SB_RIGHT_ARROW" },
202 { GDK_SB_UP_ARROW,
"GDK_SB_UP_ARROW" },
203 { GDK_SB_V_DOUBLE_ARROW,
"GDK_SB_V_DOUBLE_ARROW" },
204 { GDK_SHUTTLE,
"GDK_SHUTTLE" },
205 { GDK_SIZING,
"GDK_SIZING" },
206 { GDK_SPIDER,
"GDK_SPIDER" },
207 { GDK_SPRAYCAN,
"GDK_SPRAYCAN" },
208 { GDK_STAR,
"GDK_STAR" },
209 { GDK_TARGET,
"GDK_TARGET" },
210 { GDK_TCROSS,
"GDK_TCROSS" },
211 { GDK_TOP_LEFT_ARROW,
"GDK_TOP_LEFT_ARROW" },
212 { GDK_TOP_LEFT_CORNER,
"GDK_TOP_LEFT_CORNER" },
213 { GDK_TOP_RIGHT_CORNER,
"GDK_TOP_RIGHT_CORNER" },
214 { GDK_TOP_SIDE,
"GDK_TOP_SIDE" },
215 { GDK_TOP_TEE,
"GDK_TOP_TEE" },
216 { GDK_TREK,
"GDK_TREK" },
217 { GDK_UL_ANGLE,
"GDK_UL_ANGLE" },
218 { GDK_UMBRELLA,
"GDK_UMBRELLA" },
219 { GDK_UR_ANGLE,
"GDK_UR_ANGLE" },
220 { GDK_WATCH,
"GDK_WATCH" },
221 { GDK_XTERM,
"GDK_XTERM" },
222 { GDK_LAST_CURSOR,
"GDK_LAST_CURSOR" },
223 { GDK_BLANK_CURSOR,
"GDK_BLANK_CURSOR" },
224 { GDK_CURSOR_IS_PIXMAP,
"GDK_CURSOR_IS_PIXMAP" },
227 for(
size_t i = 0;
i <
sizeof(cursor_names) /
sizeof(cursor_names[0]);
i++)
228 if(cursor_names[
i].shape == cursor)
return cursor_names[
i].name;
230 return "GDK_CURSOR_UNKNOWN";
247 GdkWindow *
window = gtk_widget_get_window(widget);
259 if(gtk_widget_get_window(center_base) != gtk_widget_get_window(main_window))
262 if(gtk_widget_get_window(center) != gtk_widget_get_window(center_base)
263 && gtk_widget_get_window(center) != gtk_widget_get_window(main_window))
269 gchar *current_shape_str = g_strdup(shape_str);
290 const gboolean current_is_named_cursor =
295 if(g_strcmp0(curs_str,
"progress") != 0)
304 else if(current_is_named_cursor)
309 const dt_cursor_t chosen_shape = hide ? GDK_BLANK_CURSOR : GDK_CURSOR_IS_PIXMAP;
310 GdkCursor *cursor_shape = hide
311 ? gdk_cursor_new_for_display(gdk_display_get_default(), GDK_BLANK_CURSOR)
312 : gdk_cursor_new_from_name(gdk_display_get_default(), curs_str);
321 g_object_unref(cursor_shape);
339 GdkDisplay *display = gdk_display_get_default();
340 if(!
IS_NULL_PTR(display)) gdk_display_flush(display);
360 const dt_cursor_t requested_shape = cursor == GDK_CURSOR_IS_PIXMAP ? GDK_LEFT_PTR : cursor;
361 const dt_cursor_t chosen_shape = hide ? GDK_BLANK_CURSOR : requested_shape;
372 GdkCursor *cursor_shape = gdk_cursor_new_for_display(gdk_display_get_default(), chosen_shape);
375 g_object_unref(cursor_shape);
380 "Changing cursor to `%s`, requested from %s:%d\n",
387 const dt_cursor_t requested_shape = cursor == GDK_CURSOR_IS_PIXMAP ? GDK_LEFT_PTR : cursor;
412 if(g_strcmp0(curs_str,
"progress") == 0)
417 GdkCursor *cursor = gdk_cursor_new_from_name(gdk_display_get_default(), curs_str);
419 g_object_unref(cursor);
462 if(gtk_main_level() > 0) gtk_main_quit();
472 pthread_cond_broadcast(&s->
cond);
480 pthread_join(s->
thread[
k], NULL);
524 GdkRGBA
color, fallback = {1.0, 0.0, 0.0, 1.0};
525 if(!gtk_style_context_lookup_color (context,
name, &
color))
534 PangoFontDescription *desc = pango_font_description_copy_static(
dt_bauhaus_get_global()->pango_font_desc);
536 pango_font_description_set_absolute_size(desc, fontsize * PANGO_SCALE);
537 pango_font_description_set_weight(desc, PANGO_WEIGHT_BOLD);
538 layout = pango_cairo_create_layout(cr);
539 pango_layout_set_font_description(layout, desc);
543 pango_layout_set_text(layout, !
IS_NULL_PTR(message) ? message : _(
"Working..."), -1);
545 pango_layout_get_pixel_extents(layout, &ink, NULL);
546 if(ink.width >
width * 0.98)
548 pango_layout_set_text(layout,
"...", -1);
549 pango_layout_get_pixel_extents(layout, &ink, NULL);
552 cairo_move_to(cr, xc - wd, yc + 1. / 3. * fontsize - fontsize);
553 pango_cairo_layout_path(cr, layout);
554 cairo_set_line_width(cr, 2.0);
556 cairo_stroke_preserve(cr);
559 pango_font_description_free(desc);
560 g_object_unref(layout);
570 GdkSeat *seat =
IS_NULL_PTR(display) ? NULL : gdk_display_get_default_seat(display);
571 GdkDevice *pointer =
IS_NULL_PTR(seat) ? NULL : gdk_seat_get_pointer(seat);
574 GdkModifierType mask = 0;
575 gdk_window_get_device_position(
window, pointer, NULL, NULL, &mask);
579 case 1:
return (mask & GDK_BUTTON1_MASK) != 0;
580 case 2:
return (mask & GDK_BUTTON2_MASK) != 0;
581 case 3:
return (mask & GDK_BUTTON3_MASK) != 0;
582 default:
return FALSE;
597 int pointerx, pointery;
599 gdk_window_get_device_position(gtk_widget_get_window(widget),
600 gdk_seat_get_pointer(gdk_display_get_default_seat(gtk_widget_get_display(widget))),
601 &pointerx, &pointery, NULL);
606 GtkStyleContext *context = gtk_widget_get_style_context(widget);
619 gdk_cairo_set_source_rgba(cr, &bg_color);
644 cairo_rectangle(cr, 0,
height - progress_h,
647 cairo_set_source_rgba(cr, 0., 0., 0., 0.33);
682 gtk_widget_set_tooltip_text(widget,
"");
687 const char *mode = (
const char*)user_data;
704 if(current_view && !strcmp(mode, current_view->
module_name))
722 const int32_t imgid = GPOINTER_TO_INT(user_data);
783 const float yc = ht * 0.85 + 10;
785 if(which == 1 && y > yc - 10 && y < yc + 10)
801 if(which == 1 && y > yc - 10 && y < yc + 10)
829 char *escaped_msg = g_markup_vprintf_escaped(msg, ap);
830 const int msglen = strlen(escaped_msg);
847static void _toast_log(
const gboolean markup,
const char *msg, va_list ap)
856 char *escaped_msg = g_markup_vprintf_escaped(msg, ap);
955 gtk_widget_queue_draw(widget);
956 g_object_unref(widget);
976 g_weak_ref_init(&redraw_widget->
widget_ref, G_OBJECT(widget));
GtkWidget * dt_gui_main_window(void)
struct dt_ui_t * dt_gui_get_ui(void)
GtkWidget * dt_gui_center_widget(void)
struct _GtkWidget GtkWidget
GtkWidget, opaque, spelled exactly as GTK spells it.
void dt_ctl_switch_mode_to(const char *mode)
static int _widget_queue_draw(void *widget_data)
void dt_control_set_cursor_visible_EXT(gboolean visible, const char *file, int line)
Set whether the cursor should be visible or not.
void dt_control_key_pressed(GdkEventKey *event)
static void _dt_ctl_switch_mode_prepare()
void dt_control_init(dt_control_t *s)
static void _control_set_cursor_on_widget(GtkWidget *widget, GdkCursor *cursor)
int32_t dt_control_get_mouse_over_id()
void dt_control_draw_busy_msg(cairo_t *cr, int width, int height)
void dt_control_mouse_is_dragging(gboolean state)
void dt_control_button_pressed(double x, double y, double pressure, int which, int type, uint32_t state)
void dt_toast_log(const char *msg,...)
void dt_ctl_switch_mode_to_by_view(const dt_view_t *view)
void dt_control_queue_cursor_EXT(dt_cursor_t cursor, const char *file, int line)
void dt_control_get_pointer_input(dt_control_pointer_input_t *input)
void dt_control_set_mouse_over_id(int32_t value)
static gboolean _redraw_center(gpointer user_data)
void dt_control_forbid_change_cursor()
void dt_toast_markup_log(const char *msg,...)
void dt_control_log(const char *msg,...)
static GdkRGBA lookup_color(GtkStyleContext *context, const char *name)
void dt_control_queue_redraw_center()
Request a redraw of the centre view.
static gboolean _dt_ctl_switch_mode_to_by_view(gpointer user_data)
void dt_control_mouse_leave()
void dt_control_toast_busy_enter()
void dt_control_shutdown(dt_control_t *s)
void dt_control_log_busy_leave()
void dt_control_mouse_is_painting(gboolean state)
gboolean dt_control_configure(GtkWidget *da, GdkEventConfigure *event, gpointer user_data)
void dt_control_change_cursor_by_name_and_flush(const char *curs_str)
Apply a named cursor immediatelly and flush display updates for immediate feedback.
void dt_control_cleanup(dt_control_t *s)
static const char * _get_cursor_name(dt_cursor_t cursor)
Human-readable name of a GDK cursor shape, for debug output.
void dt_control_button_released(double x, double y, int which, uint32_t state)
void dt_control_commit_cursor()
void dt_control_set_pointer_input(const dt_control_pointer_input_t *input)
static void _control_store_current_cursor(const dt_cursor_t shape, const char *shape_str)
void dt_control_change_cursor_by_name(const char *curs_str)
Apply a GTK named cursor without changing the queued cursor.
void dt_control_allow_change_cursor()
static void _control_apply_cursor(GdkCursor *cursor)
void dt_ctl_open_image_in_darkroom(const int32_t imgid)
open one specific image in the darkroom, from any view and any thread.
void dt_control_log_busy_enter()
static dt_control_pointer_input_t _pointer_input
void dt_control_mouse_moved(double x, double y, double pressure, int which)
void dt_control_queue_redraw_widget(GtkWidget *widget)
threadsafe request of redraw of specific widget. Use this function if you need to redraw a specific w...
void dt_control_hinter_message(const struct dt_control_t *s, const char *message)
int32_t dt_control_get_keyboard_over_id()
void dt_control_toast_redraw()
Request a redraw of the toast message label.
void dt_control_mouse_enter()
void dt_control_change_cursor_EXT(dt_cursor_t cursor, const char *file, int line)
void dt_control_log_redraw()
Request a redraw of the log message label.
static gboolean _dt_ctl_toast_message_timeout_callback(gpointer data)
void dt_control_navigation_redraw()
Request a redraw of the navigation module's widget.
void dt_control_expose(cairo_t *cr, const int width, const int height)
static void _widget_queue_draw_cleanup(void *widget_data)
void dt_control_toast_busy_leave()
void dt_control_queue_cursor_by_name(const char *curs_str)
Queue a GTK named cursor for the next cursor commit.
static void _toast_log(const gboolean markup, const char *msg, va_list ap)
static gboolean _dt_ctl_open_image_in_darkroom(gpointer user_data)
static gboolean _dt_ctl_log_message_timeout_callback(gpointer data)
gboolean dt_control_button_down(int which)
Is mouse button which currently held down?
static gboolean _dt_ctl_switch_mode_to(gpointer user_data)
void dt_control_queue_redraw()
Request a redraw of the whole workspace.
void dt_control_set_keyboard_over_id(int32_t value)
#define DT_CTL_LOG_TIMEOUT
#define DT_CTL_TOAST_SIZE
#define DT_CTL_TOAST_MSG_SIZE
char * dt_get_main_message_copy(void)
#define dt_control_change_cursor(cursor)
#define DT_CTL_LOG_MSG_SIZE
#define DT_CTL_TOAST_TIMEOUT
GdkCursorType dt_cursor_t
struct dt_gui_gtk_t * dt_gui_get_global(void)
struct dt_bauhaus_t * dt_bauhaus_get_global(void)
GtkWidget * view
the tree view
static int dt_pthread_mutex_unlock(dt_pthread_mutex_t *mutex) RELEASE(mutex) NO_THREAD_SAFETY_ANALYSIS
static int dt_pthread_mutex_init(dt_pthread_mutex_t *mutex, const pthread_mutexattr_t *mutexattr)
Initialise a mutex. With mutexattr NULL – which is how 54 of the 56 call sites in this tree spell it ...
static int dt_pthread_mutex_destroy(dt_pthread_mutex_t *mutex)
static int dt_pthread_mutex_lock(dt_pthread_mutex_t *mutex) ACQUIRE(mutex) NO_THREAD_SAFETY_ANALYSIS
void dt_control_jobs_drain(dt_control_t *control)
void dt_control_jobs_cleanup(dt_control_t *control)
void dt_control_jobs_init(dt_control_t *control)
#define DT_CTL_WORKER_RESERVED
_lib_location_type_t type
int32_t dt_get_debug_flags(void)
void dt_print(dt_debug_thread_t thread, const char *msg,...) __attribute__((format(printf
Print to stdout when thread is enabled, prefixed with seconds since startup.
float *const restrict const size_t k
#define IS_NULL_PTR(p)
C is way too permissive with !=, == and if(var) checks, which can mean too many things depending on w...
#define dt_free(ptr)
g_free() ptr and set it to NULL, skipping both if it is already NULL.
struct dt_selection_t * dt_selection_get_global(void)
void dt_selection_select_single(dt_selection_t *selection, int32_t imgid)
#define DT_DEBUG_CONTROL_SIGNAL_RAISE(ctlsig, signal,...)
struct dt_control_signal_t * dt_control_signal_get_global(void)
@ DT_SIGNAL_CONTROL_REDRAW_ALL
This signal is raised when dt_control_queue_redraw() is called. no param, no returned value.
@ DT_SIGNAL_MOUSE_OVER_IMAGE_CHANGE
This signal is raised when mouse hovers over image thumbs both on lighttable and in the filmstrip....
@ DT_SIGNAL_CONTROL_TOAST_REDRAW
This signal is raised when dt_control_toast_redraw() is called. no param, no returned value.
@ DT_SIGNAL_CONTROL_REDRAW_CENTER
This signal is raised when dt_control_queue_redraw_center() is called. no param, no returned value.
@ DT_SIGNAL_CONTROL_LOG_REDRAW
This signal is raised when dt_control_log_redraw() is called. no param, no returned value.
@ DT_SIGNAL_CONTROL_NAVIGATION_REDRAW
This signal is raised when dt_control_navigation_redraw() is called. no param, no returned value.
static const dt_aligned_pixel_simd_t value
const float uint32_t state[4]
struct dt_develop_t * develop
struct dt_view_manager_t * view_manager
struct dt_control_t * control
dt_pthread_mutex_t run_mutex
char toast_message[10][300]
gchar * current_shape_str
pthread_t thread_res[DT_CTL_WORKER_RESERVED]
dt_pthread_mutex_t log_mutex
guint log_message_timeout_id
guint toast_message_timeout_id
dt_pthread_mutex_t res_mutex
dt_cursor_t current_shape
pthread_t kick_on_workers_thread
dt_pthread_mutex_t queue_mutex
struct dt_control_t::@7 cursor
dt_pthread_mutex_t toast_mutex
char log_message[10][1000]
dt_pthread_mutex_t cond_mutex
dt_pthread_mutex_t global_mutex
struct dt_control_t::@8 progress_system
struct dt_develop_t::@20 progress
struct dt_gui_gtk_t::@33 mouse
void dt_view_manager_mouse_moved(dt_view_manager_t *vm, double x, double y, double pressure, int which)
void dt_view_manager_mouse_enter(dt_view_manager_t *vm)
void dt_view_manager_configure(dt_view_manager_t *vm, int width, int height)
int dt_view_manager_button_released(dt_view_manager_t *vm, double x, double y, int which, uint32_t state)
void dt_view_manager_expose(dt_view_manager_t *vm, cairo_t *cr, int32_t width, int32_t height, int32_t pointerx, int32_t pointery)
int dt_view_manager_key_pressed(dt_view_manager_t *vm, GdkEventKey *event)
int dt_view_manager_button_pressed(dt_view_manager_t *vm, double x, double y, double pressure, int which, int type, uint32_t state)
uint32_t dt_view_manager_current_flags(const dt_view_manager_t *vm)
int dt_view_manager_switch(dt_view_manager_t *vm, const char *view_name)
int dt_view_manager_switch_by_view(dt_view_manager_t *vm, const dt_view_t *nv)
void dt_view_manager_mouse_leave(dt_view_manager_t *vm)
const dt_view_t * dt_view_manager_get_current_view(dt_view_manager_t *vm)
@ VIEW_FLAGS_PAINTS_WHOLE_AREA
void dt_hinter_set_message(dt_ui_t *ui, const char *message)
GtkWidget * dt_ui_center_base(dt_ui_t *ui)