Compare commits

..

44 Commits

Author SHA1 Message Date
Matthias Clasen
d305148912 tooltip: Prevent too-wide tooltip windows
Set the label to expand, so it actually fills
the width that we allocated for it, instead
of shrinking back to the minimum width for
its height.

Fixes: #5521
2023-01-28 10:33:40 -05:00
Matthias Clasen
4b6a9d2fb5 tooltip: Don't play games with max-width-chars
Setting max-width-chars to the number of characters
in the string works ok only as long as the average
char width we get from Pango matches reality. Sadly
that seems not always the case, and this code was
causing short Chinese tooltips to always be broken
into two lines.

Fixes: #4470
2023-01-28 10:33:40 -05:00
Piotr Drąg
56c1c4152f Update POTFILES.in 2023-01-28 14:05:01 +01:00
Matthias Clasen
a9d2fa296e Merge branch 'position-as-double' into 'main'
Boyscouting: fix position type in `gtk_drag_source_drag_begin()`

See merge request GNOME/gtk!5437
2023-01-28 03:24:19 +00:00
Carlos Garnacho
5bccb106c2 Merge branch 'work/zzag/activation-token-dbus' into 'main'
wayland: Fix handling of activation-token in org.freedesktop.Application requests

See merge request GNOME/gtk!5151
2023-01-28 00:44:25 +00:00
Yuri Chornoivan
45086487f1 Update Ukrainian translation 2023-01-27 19:23:39 +00:00
Vlad Zahorodnii
65f03121a4 wayland: Fix handling of activation-token in org.freedesktop.Application requests
At the moment, GTK applications search for "desktop-startup-id" in the
platform data on Wayland , but desktop environments such as plasma set
"activation-token" property instead as indicated in the spec:

    activation-token: This should be a string of the same value as would
    be stored in the XDG_ACTIVATION_TOKEN environment variable, as specified
    by the XDG Activation protocol for Wayland.

https://specifications.freedesktop.org/desktop-entry-spec/desktop-entry-spec-latest.html#dbus
2023-01-27 19:20:53 +00:00
Carlos Garnacho
09769193d7 Merge branch 'wip/carlosg/broadway-fix' into 'main'
gdk/broadway: Add deprecation guards around gdk_display_put_event()

See merge request GNOME/gtk!5450
2023-01-27 19:20:28 +00:00
Carlos Garnacho
7f8acf960b gdk/broadway: Add deprecation guards around gdk_display_put_event()
This went missing.
2023-01-27 19:59:36 +01:00
Matthias Clasen
ee0e026237 Merge branch 'fix_5551' into 'main'
object_tree.c: One gtk_list_item_get_child call is redundant

Closes #5551

See merge request GNOME/gtk!5449
2023-01-27 16:22:17 +00:00
Matthias Clasen
6bfd581a72 Merge branch 'wip/sophie-h/scrolled-window-propagate-event' into 'main'
scrolledWindow: Propagate event for no scrolling

See merge request GNOME/gtk!5447
2023-01-27 14:54:33 +00:00
Lukáš Tyrychtr
7b6f254e64 object_tree.c: One gtk_list_item_get_child call is redundant
Fixes #5551
2023-01-27 15:43:33 +01:00
Hugo Carvalho
47955cfe62 Update Portuguese translation 2023-01-27 14:26:32 +00:00
Sophie Herold
e62ca17f88 scrolledWindow: Propagate event for no scrolling 2023-01-26 20:12:10 +01:00
Matthias Clasen
c24ba58acb Merge branch 'broadway-modal-hint' into 'main'
[GTK4] gdk/broadway: Implements modal hint for Broadway surface

See merge request GNOME/gtk!4428
2023-01-26 02:44:54 +00:00
Matthias Clasen
30987168fb Merge branch 'fix_5543' into 'main'
GtkCssProvider: fix element type in docs

Closes #5543

See merge request GNOME/gtk!5441
2023-01-25 13:08:07 +00:00
Lukáš Tyrychtr
93a875bf20 Actually, the annotation is not needed in this case 2023-01-25 11:46:53 +01:00
Yosef Or Boczko
aac3bf581a Update Hebrew translation 2023-01-25 08:15:09 +00:00
Matthias Clasen
869f07521c Merge branch 'macos-fix-popups' into 'main'
macos: Fix popup event handling

Closes #5528

See merge request GNOME/gtk!5436
2023-01-24 16:37:23 +00:00
Matthias Clasen
7e392a1186 Merge branch 'wip/abono/gtk-switch-state-off' into 'main'
gtkswitch: Allow to set state FALSE while keeping active TRUE

See merge request GNOME/gtk!5442
2023-01-24 16:08:57 +00:00
Alessandro Bono
53d87e42a5 gtkswitch: Decouple set_state with set_active.
Allow the user to set a state that doesn't reflect the active property.
2023-01-24 14:55:16 +01:00
Arjan Molenaar
6757a1b409 macos: Propagate events for child surfaces
Before, popup windows did not respond to mouse clicks.
This change fixes that.

Fixes #5528.
2023-01-24 09:07:33 +01:00
Maxim Zakharov
115738dd2f remove unused variable 2023-01-24 11:41:27 +11:00
Matthias Clasen
5caa66ffb7 Merge branch 'macos-native-dnd' into 'main'
macos: DnD Drag support

Closes #3423

See merge request GNOME/gtk!5416
2023-01-23 22:01:30 +00:00
Emmanuele Bassi
7df73c4fd2 Use wording from a suggestion 2023-01-23 11:50:28 +00:00
Lukáš Tyrychtr
1ea5a08c8f GtkCssProvider: fix element type in docs
The method takes an array of char, which actually is UTF-8, so make the docs say so.
Fixes #5543
2023-01-23 12:12:00 +01:00
Matthias Clasen
9c669cbe90 Merge branch 'matthiasc/for-main' into 'main'
iconhelper: Handle GtkSymbolicPaintable

See merge request GNOME/gtk!5440
2023-01-22 18:36:11 +00:00
Matthias Clasen
1a5184bc85 iconhelper: Handle GtkSymbolicPaintable
If we are given a GtkSymbolicPaintable,
treat it as symbolic.
2023-01-22 13:18:18 -05:00
Arjan Molenaar
d6ef39b9a2 macos: remove dead code 2023-01-21 15:22:13 +01:00
Arjan Molenaar
52f6acd398 macos: Send dragging events directly to the display
Instead of adding events to the application event queue, dispatch
them directly to the right display. We know this when the event is
to be dispatched.

This is the same as used for the `sendEvent` method in `GdkMacosWindow`.

To achieve this I factored out the generic NSEvent to GdkEvent translation.
We can send an event directly, when we receive it in the GdkMacosWindow
directly from the OS.
2023-01-21 14:54:12 +01:00
Arjan Molenaar
136c1ccd2c macos: Update event source doc
Update the documentation with the interaction pattern we
need to support DnD.
2023-01-17 16:37:21 +01:00
Arjan Molenaar
16e23b3f9e macos: align functions in gdkmacosdrag-private.h 2023-01-17 16:12:57 +01:00
Arjan Molenaar
628aeda7ee macos: Provide the right drag action
We should use the drag action/operation provided by the
drag handlers, not rely on our internal bookkeeping.
2023-01-16 23:21:35 +01:00
Arjan Molenaar
2669dc269b macos: Default kCFRunLoopAllActivities
It's actually a mask, but we'll keep it in to
avoid compiler warnings.
2023-01-16 20:28:38 +01:00
Arjan Molenaar
1bc63eeadb macos: Queue events during drag
By passing the events during a (midal-ish) drag operation to the main loop,
we're able to keep up with what's happening. This allows the internal
drag state (GtkDragSource) to be updated and be done when the drag is
done.
2023-01-16 14:47:49 +01:00
Arjan Molenaar
1d8a23e97b macos: Provide fallback pasteboard for gtype Dnd
The Drag data should pass through the macos pasteboard system.
We need to provide some pasteboard type. Let's make it a "URL",
which is a pretty generic type anyway.
2023-01-15 10:03:47 +01:00
Arjan Molenaar
422b4b6561 macos: No need to drag handle events
This is handled by the DraggingSource object.
2023-01-15 10:03:47 +01:00
Arjan Molenaar
27ee8b23fd macos: No need to grab a seat
The macOS DnD logic will take over anyway.
2023-01-15 10:03:47 +01:00
Arjan Molenaar
b9847795a7 macos: Support dragging from GdkMacosWindow
The handling is done similar to drag targets.
Note that dragging is a modal action on macos: no events
are sent to the main window. This could cause trouble when
we finish the drag, and not finish the gesture in GTK.
2023-01-15 10:01:56 +01:00
Arjan Molenaar
757d1916ae Fix dx, dy position in gtk_drag_source_drag_begin
Coordinates are double. This change avoid an unneeded cast.
2023-01-15 09:52:43 +01:00
Arjan Molenaar
420be8fb0f macos: run glib idle functions when in nested run loop
It looks like DnD starts a nested run loop. We still have to run our
GLib handlers, so animations work.
2023-01-13 20:03:55 +01:00
Christian Hergert
9c3629653f macos: abstract pasteboard for use in clipboard and drag
This will allow us to share a single NSPasteboardItem and data provider
implementation for both GdkClipboard and GdkDrag.
2023-01-13 20:03:55 +01:00
Christian Hergert
eb5cf831b1 macos: refactor pasteboard components into separate module
This will make it easier to reuse from drag integration so that we don't
require clipboards for everything.

We will need to subclass the pasteboard provider twice, however, both
for clipboard and dragging.
2023-01-13 20:03:55 +01:00
Maxim Zakharov
2290c2bb23 gdk/broadway: Implements modal hint for Broadway surface
Ensures modal window is raised above parent; does return focus to
parent window when transient child window is closed.

That solves problems with overlapped modal window and focus loss in
complex multi window UI.
2022-05-17 15:18:30 +10:00
37 changed files with 2166 additions and 1908 deletions

View File

@@ -213,6 +213,7 @@ typedef enum {
BROADWAY_REQUEST_RELEASE_TEXTURE,
BROADWAY_REQUEST_SET_NODES,
BROADWAY_REQUEST_ROUNDTRIP,
BROADWAY_REQUEST_SET_MODAL_HINT,
} BroadwayRequestType;
typedef struct {
@@ -293,6 +294,12 @@ typedef struct {
guint32 show_keyboard;
} BroadwayRequestSetShowKeyboard;
typedef struct {
BroadwayRequestBase base;
guint32 id;
gboolean modal_hint;
} BroadwayRequestSetModalHint;
typedef union {
BroadwayRequestBase base;
BroadwayRequestNewSurface new_surface;
@@ -312,6 +319,7 @@ typedef union {
BroadwayRequestUploadTexture upload_texture;
BroadwayRequestReleaseTexture release_texture;
BroadwayRequestSetNodes set_nodes;
BroadwayRequestSetModalHint set_modal_hint;
} BroadwayRequest;
typedef enum {

View File

@@ -124,6 +124,7 @@ struct BroadwaySurface {
gboolean visible;
gint32 transient_for;
guint32 texture;
gboolean modal_hint;
BroadwayNode *nodes;
GHashTable *node_lookup;
};
@@ -421,6 +422,14 @@ update_event_state (BroadwayServer *server,
{
surface->x = message->configure_notify.x;
surface->y = message->configure_notify.y;
if (server->focused_surface_id != message->configure_notify.id &&
server->pointer_grab_surface_id == -1 && surface->modal_hint)
{
broadway_server_surface_raise (server, message->configure_notify.id);
broadway_server_focus_surface (server, message->configure_notify.id);
broadway_server_flush (server);
}
}
break;
case BROADWAY_EVENT_ROUNDTRIP_NOTIFY:
@@ -1568,6 +1577,7 @@ broadway_server_destroy_surface (BroadwayServer *server,
int id)
{
BroadwaySurface *surface;
gint32 transient_for = -1;
if (server->mouse_in_surface_id == id)
{
@@ -1585,11 +1595,24 @@ broadway_server_destroy_surface (BroadwayServer *server,
surface = broadway_server_lookup_surface (server, id);
if (surface != NULL)
{
if (server->focused_surface_id == id)
transient_for = surface->transient_for;
server->surfaces = g_list_remove (server->surfaces, surface);
g_hash_table_remove (server->surface_id_hash,
GINT_TO_POINTER (id));
broadway_surface_free (server, surface);
}
if (transient_for != -1)
{
surface = broadway_server_lookup_surface (server, transient_for);
if (surface != NULL)
{
broadway_server_focus_surface (server, transient_for);
broadway_server_flush (server);
}
}
}
gboolean
@@ -1710,6 +1733,19 @@ broadway_server_surface_set_transient_for (BroadwayServer *server,
}
}
void
broadway_server_surface_set_modal_hint (BroadwayServer *server,
int id, gboolean modal_hint)
{
BroadwaySurface *surface;
surface = broadway_server_lookup_surface (server, id);
if (surface == NULL)
return;
surface->modal_hint = modal_hint;
}
gboolean
broadway_server_has_client (BroadwayServer *server)
{

View File

@@ -130,6 +130,9 @@ gboolean broadway_server_surface_move_resize (BroadwayServer *
int height);
void broadway_server_focus_surface (BroadwayServer *server,
int new_focused_surface);
void broadway_server_surface_set_modal_hint (BroadwayServer *server,
int id,
gboolean modal_hint);
#endif /* __BROADWAY_SERVER__ */

View File

@@ -380,6 +380,11 @@ client_handle_request (BroadwayClient *client,
case BROADWAY_REQUEST_SET_SHOW_KEYBOARD:
broadway_server_set_show_keyboard (server, request->set_show_keyboard.show_keyboard);
break;
case BROADWAY_REQUEST_SET_MODAL_HINT:
broadway_server_surface_set_modal_hint (server,
request->set_modal_hint.id,
request->set_modal_hint.modal_hint);
break;
default:
g_warning ("Unknown request of type %d", request->base.type);
}

View File

@@ -561,6 +561,18 @@ _gdk_broadway_server_surface_set_transient_for (GdkBroadwayServer *server,
BROADWAY_REQUEST_SET_TRANSIENT_FOR);
}
void
_gdk_broadway_server_surface_set_modal_hint (GdkBroadwayServer *server,
int id, gboolean modal_hint)
{
BroadwayRequestSetModalHint msg;
msg.id = id;
msg.modal_hint = modal_hint;
gdk_broadway_server_send_message (server, msg,
BROADWAY_REQUEST_SET_MODAL_HINT);
}
static int
open_shared_memory (void)
{

View File

@@ -78,5 +78,8 @@ gboolean _gdk_broadway_server_surface_move_resize (GdkBroadwaySe
int y,
int width,
int height);
void _gdk_broadway_server_surface_set_modal_hint (GdkBroadwayServer *server,
int id,
gboolean modal_hint);
#endif /* __GDK_BROADWAY_SERVER__ */

View File

@@ -82,6 +82,27 @@ gdk_event_source_check (GSource *source)
return retval;
}
static void
handle_focus_change (GdkEvent *event)
{
GdkEvent *focus_event;
gboolean focus_in = (gdk_event_get_event_type (event) == GDK_ENTER_NOTIFY);
if (gdk_crossing_event_get_detail (event) == GDK_NOTIFY_INFERIOR)
return;
if (!gdk_crossing_event_get_focus (event) )
return;
focus_event = gdk_focus_event_new (gdk_event_get_surface (event),
gdk_event_get_device (event),
focus_in);
G_GNUC_BEGIN_IGNORE_DEPRECATIONS
gdk_display_put_event (gdk_event_get_display (event), focus_event);
G_GNUC_END_IGNORE_DEPRECATIONS
gdk_event_unref (focus_event);
}
void
_gdk_broadway_events_got_input (GdkDisplay *display,
BroadwayInputMsg *message)
@@ -110,6 +131,8 @@ _gdk_broadway_events_got_input (GdkDisplay *display,
node = _gdk_event_queue_append (display, event);
_gdk_windowing_got_event (display, node, event, message->base.serial);
handle_focus_change (event);
}
break;
case BROADWAY_EVENT_LEAVE:
@@ -126,6 +149,8 @@ _gdk_broadway_events_got_input (GdkDisplay *display,
message->crossing.mode,
GDK_NOTIFY_ANCESTOR);
handle_focus_change (event);
node = _gdk_event_queue_append (display, event);
_gdk_windowing_got_event (display, node, event, message->base.serial);
}

View File

@@ -709,6 +709,21 @@ gdk_broadway_surface_set_transient_for (GdkSurface *surface,
_gdk_broadway_server_surface_set_transient_for (display->server, impl->id, impl->transient_for);
}
static void
gdk_broadway_surface_set_modal_hint (GdkSurface *surface,
gboolean modal)
{
GdkBroadwayDisplay *display;
GdkBroadwaySurface *impl;
impl = GDK_BROADWAY_SURFACE (surface);
impl->modal_hint = modal;
display = GDK_BROADWAY_DISPLAY (gdk_surface_get_display (surface));
_gdk_broadway_server_surface_set_modal_hint (display->server, impl->id, impl->modal_hint);
}
static void
gdk_broadway_surface_get_geometry (GdkSurface *surface,
int *x,
@@ -1433,6 +1448,8 @@ gdk_broadway_toplevel_set_property (GObject *object,
break;
case LAST_PROP + GDK_TOPLEVEL_PROP_MODAL:
gdk_broadway_surface_set_modal_hint (surface, g_value_get_boolean (value));
g_object_notify_by_pspec (G_OBJECT (surface), pspec);
break;
case LAST_PROP + GDK_TOPLEVEL_PROP_ICON_LIST:
@@ -1479,6 +1496,10 @@ gdk_broadway_toplevel_get_property (GObject *object,
g_value_set_object (value, surface->transient_for);
break;
case LAST_PROP + GDK_TOPLEVEL_PROP_MODAL:
g_value_set_boolean (value, surface->modal_hint);
break;
case LAST_PROP + GDK_TOPLEVEL_PROP_ICON_LIST:
g_value_set_pointer (value, NULL);
break;

View File

@@ -54,6 +54,7 @@ struct _GdkBroadwaySurface
gboolean dirty;
gboolean last_synced;
gboolean modal_hint;
GdkGeometry geometry_hints;
GdkSurfaceHints geometry_hints_mask;

View File

@@ -27,10 +27,12 @@
#import "GdkMacosView.h"
#import "GdkMacosWindow.h"
#include "gdkmacosclipboard-private.h"
#include "gdkmacosdisplay-private.h"
#include "gdkmacosdrag-private.h"
#include "gdkmacosdrop-private.h"
#include "gdkmacoseventsource-private.h"
#include "gdkmacosmonitor-private.h"
#include "gdkmacospasteboard-private.h"
#include "gdkmacossurface-private.h"
#include "gdkmacospopupsurface-private.h"
#include "gdkmacostoplevelsurface-private.h"
@@ -144,7 +146,7 @@ typedef NSString *CALayerContentsGravity;
*
* TODO: Can we improve grab breaking to fix this?
*/
_gdk_macos_display_send_button_event ([self gdkDisplay], event);
_gdk_macos_display_send_event ([self gdkDisplay], event);
_gdk_macos_display_break_all_grabs (GDK_MACOS_DISPLAY (display), time);
@@ -246,7 +248,7 @@ typedef NSString *CALayerContentsGravity;
[view release];
/* TODO: We might want to make this more extensible at some point */
_gdk_macos_clipboard_register_drag_types (self);
_gdk_macos_pasteboard_register_drag_types (self);
return self;
}
@@ -668,7 +670,61 @@ typedef NSString *CALayerContentsGravity;
}
// NSDraggingSource protocol
// ...
- (NSDragOperation)draggingSession:(NSDraggingSession *)session sourceOperationMaskForDraggingContext:(NSDraggingContext)context
{
NSInteger sequence_number = [session draggingSequenceNumber];
GdkDisplay *display = gdk_surface_get_display (GDK_SURFACE (gdk_surface));
GdkDrag *drag = _gdk_macos_display_find_drag (GDK_MACOS_DISPLAY (display), sequence_number);
GdkModifierType state = _gdk_macos_display_get_current_keyboard_modifiers (GDK_MACOS_DISPLAY (display));
_gdk_macos_drag_set_actions (GDK_MACOS_DRAG (drag), state);
return _gdk_macos_drag_operation (GDK_MACOS_DRAG (drag));
}
- (void)draggingSession:(NSDraggingSession *)session willBeginAtPoint:(NSPoint)screenPoint
{
NSInteger sequence_number = [session draggingSequenceNumber];
GdkDisplay *display = gdk_surface_get_display (GDK_SURFACE (gdk_surface));
GdkDrag *drag = _gdk_macos_display_find_drag (GDK_MACOS_DISPLAY (display), sequence_number);
int x, y;
_gdk_macos_display_from_display_coords (GDK_MACOS_DISPLAY (display), screenPoint.x, screenPoint.y, &x, &y);
_gdk_macos_drag_set_start_position (GDK_MACOS_DRAG (drag), x, y);
_gdk_macos_drag_surface_move (GDK_MACOS_DRAG (drag), x, y);
}
- (void)draggingSession:(NSDraggingSession *)session movedToPoint:(NSPoint)screenPoint
{
NSInteger sequence_number = [session draggingSequenceNumber];
GdkMacosDisplay *display = GDK_MACOS_DISPLAY (gdk_surface_get_display (GDK_SURFACE (gdk_surface)));
GdkDrag *drag = _gdk_macos_display_find_drag (GDK_MACOS_DISPLAY (display), sequence_number);
int x, y;
_gdk_macos_display_send_event (display, [NSApp currentEvent]);
_gdk_macos_display_from_display_coords (display, screenPoint.x, screenPoint.y, &x, &y);
_gdk_macos_drag_surface_move (GDK_MACOS_DRAG (drag), x, y);
}
- (void)draggingSession:(NSDraggingSession *)session endedAtPoint:(NSPoint)screenPoint operation:(NSDragOperation)operation
{
NSInteger sequence_number = [session draggingSequenceNumber];
GdkMacosDisplay *display = GDK_MACOS_DISPLAY (gdk_surface_get_display (GDK_SURFACE (gdk_surface)));
GdkDrag *drag = _gdk_macos_display_find_drag (display, sequence_number);
_gdk_macos_display_send_event (display, [NSApp currentEvent]);
gdk_drag_set_selected_action (drag, _gdk_macos_drag_ns_operation_to_action (operation));
if (gdk_drag_get_selected_action (drag) != 0)
g_signal_emit_by_name (drag, "drop-performed");
else
gdk_drag_cancel (drag, GDK_DRAG_CANCEL_NO_TARGET);
_gdk_macos_display_set_drag (display, [session draggingSequenceNumber], NULL);
}
// end
-(void)setStyleMask:(NSWindowStyleMask)styleMask

View File

@@ -32,7 +32,7 @@
#define GDK_IS_MACOS_WINDOW(obj) ([obj isKindOfClass:[GdkMacosWindow class]])
@interface GdkMacosWindow : NSWindow {
@interface GdkMacosWindow : NSWindow <NSDraggingSource, NSDraggingDestination> {
GdkMacosSurface *gdk_surface;
BOOL inMove;

View File

@@ -24,6 +24,7 @@
#include "gdkclipboardprivate.h"
#include "gdkmacosdisplay-private.h"
#include "gdkmacospasteboard-private.h"
G_BEGIN_DECLS
@@ -41,30 +42,6 @@ NSPasteboardType _gdk_macos_clipboard_to_ns_type (const char
NSPasteboardType *alternate);
const char *_gdk_macos_clipboard_from_ns_type (NSPasteboardType ns_type);
void _gdk_macos_clipboard_register_drag_types (NSWindow *window);
GdkContentFormats *_gdk_macos_pasteboard_load_formats (NSPasteboard *pasteboard);
void _gdk_macos_pasteboard_read_async (GObject *object,
NSPasteboard *pasteboard,
GdkContentFormats *formats,
int io_priority,
GCancellable *cancellable,
GAsyncReadyCallback callback,
gpointer user_data);
GInputStream *_gdk_macos_pasteboard_read_finish (GObject *object,
GAsyncResult *result,
const char **out_mime_type,
GError **error);
@interface GdkMacosClipboardDataProvider : NSObject <NSPasteboardItemDataProvider>
{
GCancellable *cancellable;
GdkClipboard *clipboard;
char **mimeTypes;
}
-(id)initClipboard:(GdkClipboard *)gdkClipboard mimetypes:(const char * const *)mime_types;
-(NSArray<NSPasteboardType> *)types;
@end
G_END_DECLS

View File

@@ -22,6 +22,7 @@
#include <glib/gi18n.h>
#include "gdkmacosclipboard-private.h"
#include "gdkmacospasteboard-private.h"
#include "gdkmacosutils-private.h"
#include "gdkprivate.h"
@@ -32,163 +33,8 @@ struct _GdkMacosClipboard
NSInteger last_change_count;
};
typedef struct
{
GMemoryOutputStream *stream;
NSPasteboardItem *item;
NSPasteboardType type;
GMainContext *main_context;
guint done : 1;
} WriteRequest;
enum {
TYPE_STRING,
TYPE_PBOARD,
TYPE_URL,
TYPE_FILE_URL,
TYPE_COLOR,
TYPE_TIFF,
TYPE_PNG,
TYPE_LAST
};
#define PTYPE(k) (get_pasteboard_type(TYPE_##k))
static NSPasteboardType pasteboard_types[TYPE_LAST];
G_DEFINE_TYPE (GdkMacosClipboard, _gdk_macos_clipboard, GDK_TYPE_CLIPBOARD)
static NSPasteboardType
get_pasteboard_type (int type)
{
static gsize initialized = FALSE;
g_assert (type >= 0);
g_assert (type < TYPE_LAST);
if (g_once_init_enter (&initialized))
{
pasteboard_types[TYPE_PNG] = NSPasteboardTypePNG;
pasteboard_types[TYPE_STRING] = NSPasteboardTypeString;
pasteboard_types[TYPE_TIFF] = NSPasteboardTypeTIFF;
pasteboard_types[TYPE_COLOR] = NSPasteboardTypeColor;
G_GNUC_BEGIN_IGNORE_DEPRECATIONS
pasteboard_types[TYPE_PBOARD] = NSStringPboardType;
G_GNUC_END_IGNORE_DEPRECATIONS
#ifdef AVAILABLE_MAC_OS_X_VERSION_10_13_AND_LATER
pasteboard_types[TYPE_URL] = NSPasteboardTypeURL;
pasteboard_types[TYPE_FILE_URL] = NSPasteboardTypeFileURL;
#else
pasteboard_types[TYPE_URL] = [[NSString alloc] initWithUTF8String:"public.url"];
pasteboard_types[TYPE_FILE_URL] = [[NSString alloc] initWithUTF8String:"public.file-url"];
#endif
g_once_init_leave (&initialized, TRUE);
}
return pasteboard_types[type];
}
static void
write_request_free (WriteRequest *wr)
{
g_clear_pointer (&wr->main_context, g_main_context_unref);
g_clear_object (&wr->stream);
[wr->item release];
g_slice_free (WriteRequest, wr);
}
const char *
_gdk_macos_clipboard_from_ns_type (NSPasteboardType type)
{
G_GNUC_BEGIN_IGNORE_DEPRECATIONS;
if ([type isEqualToString:PTYPE(STRING)] ||
[type isEqualToString:PTYPE(PBOARD)])
return g_intern_string ("text/plain;charset=utf-8");
else if ([type isEqualToString:PTYPE(URL)] ||
[type isEqualToString:PTYPE(FILE_URL)])
return g_intern_string ("text/uri-list");
else if ([type isEqualToString:PTYPE(COLOR)])
return g_intern_string ("application/x-color");
else if ([type isEqualToString:PTYPE(TIFF)])
return g_intern_string ("image/tiff");
else if ([type isEqualToString:PTYPE(PNG)])
return g_intern_string ("image/png");
G_GNUC_END_IGNORE_DEPRECATIONS;
return NULL;
}
NSPasteboardType
_gdk_macos_clipboard_to_ns_type (const char *mime_type,
NSPasteboardType *alternate)
{
if (alternate)
*alternate = NULL;
if (g_strcmp0 (mime_type, "text/plain;charset=utf-8") == 0)
{
return PTYPE(STRING);
}
else if (g_strcmp0 (mime_type, "text/uri-list") == 0)
{
if (alternate)
*alternate = PTYPE(URL);
return PTYPE(FILE_URL);
}
else if (g_strcmp0 (mime_type, "application/x-color") == 0)
{
return PTYPE(COLOR);
}
else if (g_strcmp0 (mime_type, "image/tiff") == 0)
{
return PTYPE(TIFF);
}
else if (g_strcmp0 (mime_type, "image/png") == 0)
{
return PTYPE(PNG);
}
return nil;
}
static void
populate_content_formats (GdkContentFormatsBuilder *builder,
NSPasteboardType type)
{
const char *mime_type;
g_return_if_fail (builder != NULL);
g_return_if_fail (type != NULL);
mime_type = _gdk_macos_clipboard_from_ns_type (type);
if (mime_type != NULL)
gdk_content_formats_builder_add_mime_type (builder, mime_type);
}
static GdkContentFormats *
load_offer_formats (NSPasteboard *pasteboard)
{
GDK_BEGIN_MACOS_ALLOC_POOL;
GdkContentFormatsBuilder *builder;
GdkContentFormats *formats;
builder = gdk_content_formats_builder_new ();
for (NSPasteboardType type in [pasteboard types])
populate_content_formats (builder, type);
formats = gdk_content_formats_builder_free_to_formats (builder);
GDK_END_MACOS_ALLOC_POOL;
return g_steal_pointer (&formats);
}
static void
_gdk_macos_clipboard_load_contents (GdkMacosClipboard *self)
{
@@ -199,22 +45,13 @@ _gdk_macos_clipboard_load_contents (GdkMacosClipboard *self)
change_count = [self->pasteboard changeCount];
formats = load_offer_formats (self->pasteboard);
formats = _gdk_macos_pasteboard_load_formats (self->pasteboard);
gdk_clipboard_claim_remote (GDK_CLIPBOARD (self), formats);
gdk_content_formats_unref (formats);
self->last_change_count = change_count;
}
static GInputStream *
create_stream_from_nsdata (NSData *data)
{
const guint8 *bytes = [data bytes];
gsize len = [data length];
return g_memory_input_stream_new_from_data (g_memdup2 (bytes, len), len, g_free);
}
static void
_gdk_macos_clipboard_read_async (GdkClipboard *clipboard,
GdkContentFormats *formats,
@@ -245,34 +82,26 @@ static void
_gdk_macos_clipboard_send_to_pasteboard (GdkMacosClipboard *self,
GdkContentProvider *content)
{
GdkMacosPasteboardItem *item;
NSArray<NSPasteboardItem *> *items;
g_assert (GDK_IS_MACOS_CLIPBOARD (self));
g_assert (GDK_IS_CONTENT_PROVIDER (content));
if (self->pasteboard == NULL)
return;
GDK_BEGIN_MACOS_ALLOC_POOL;
GdkMacosClipboardDataProvider *dataProvider;
GdkContentFormats *serializable;
NSPasteboardItem *item;
const char * const *mime_types;
gsize n_mime_types;
g_return_if_fail (GDK_IS_MACOS_CLIPBOARD (self));
g_return_if_fail (GDK_IS_CONTENT_PROVIDER (content));
serializable = gdk_content_provider_ref_storable_formats (content);
serializable = gdk_content_formats_union_serialize_mime_types (serializable);
mime_types = gdk_content_formats_get_mime_types (serializable, &n_mime_types);
dataProvider = [[GdkMacosClipboardDataProvider alloc] initClipboard:GDK_CLIPBOARD (self)
mimetypes:mime_types];
item = [[NSPasteboardItem alloc] init];
[item setDataProvider:dataProvider forTypes:[dataProvider types]];
item = [[GdkMacosPasteboardItem alloc] initForClipboard:GDK_CLIPBOARD (self) withContentProvider:content];
items = [NSArray arrayWithObject:item];
[self->pasteboard clearContents];
if ([self->pasteboard writeObjects:[NSArray arrayWithObject:item]] == NO)
g_warning ("Failed to write object to pasteboard");
if ([self->pasteboard writeObjects:items] == NO)
g_warning ("Failed to send clipboard to pasteboard");
self->last_change_count = [self->pasteboard changeCount];
g_clear_pointer (&serializable, gdk_content_formats_unref);
GDK_END_MACOS_ALLOC_POOL;
}
@@ -365,305 +194,3 @@ _gdk_macos_clipboard_check_externally_modified (GdkMacosClipboard *self)
if ([self->pasteboard changeCount] != self->last_change_count)
_gdk_macos_clipboard_load_contents (self);
}
@implementation GdkMacosClipboardDataProvider
-(id)initClipboard:(GdkClipboard *)gdkClipboard mimetypes:(const char * const *)mime_types;
{
[super init];
self->mimeTypes = g_strdupv ((char **)mime_types);
self->clipboard = g_object_ref (gdkClipboard);
return self;
}
-(void)dealloc
{
g_cancellable_cancel (self->cancellable);
g_clear_pointer (&self->mimeTypes, g_strfreev);
g_clear_object (&self->clipboard);
g_clear_object (&self->cancellable);
[super dealloc];
}
-(void)pasteboardFinishedWithDataProvider:(NSPasteboard *)pasteboard
{
g_clear_object (&self->clipboard);
}
-(NSArray<NSPasteboardType> *)types
{
NSMutableArray *ret = [[NSMutableArray alloc] init];
for (guint i = 0; self->mimeTypes[i]; i++)
{
const char *mime_type = self->mimeTypes[i];
NSPasteboardType type;
NSPasteboardType alternate = nil;
if ((type = _gdk_macos_clipboard_to_ns_type (mime_type, &alternate)))
{
[ret addObject:type];
if (alternate)
[ret addObject:alternate];
}
}
return g_steal_pointer (&ret);
}
static void
on_data_ready_cb (GObject *object,
GAsyncResult *result,
gpointer user_data)
{
GDK_BEGIN_MACOS_ALLOC_POOL;
GdkClipboard *clipboard = (GdkClipboard *)object;
WriteRequest *wr = user_data;
GError *error = NULL;
NSData *data = nil;
g_assert (GDK_IS_CLIPBOARD (clipboard));
g_assert (G_IS_ASYNC_RESULT (result));
g_assert (wr != NULL);
g_assert (G_IS_MEMORY_OUTPUT_STREAM (wr->stream));
g_assert ([wr->item isKindOfClass:[NSPasteboardItem class]]);
if (gdk_clipboard_write_finish (clipboard, result, &error))
{
gsize size;
gpointer bytes;
g_output_stream_close (G_OUTPUT_STREAM (wr->stream), NULL, NULL);
size = g_memory_output_stream_get_data_size (wr->stream);
bytes = g_memory_output_stream_steal_data (wr->stream);
data = [[NSData alloc] initWithBytesNoCopy:bytes
length:size
deallocator:^(void *alloc, NSUInteger length) { g_free (alloc); }];
}
else
{
g_warning ("Failed to serialize clipboard contents: %s",
error->message);
g_clear_error (&error);
}
[wr->item setData:data forType:wr->type];
wr->done = TRUE;
GDK_END_MACOS_ALLOC_POOL;
}
-(void) pasteboard:(NSPasteboard *)pasteboard
item:(NSPasteboardItem *)item
provideDataForType:(NSPasteboardType)type
{
const char *mime_type = _gdk_macos_clipboard_from_ns_type (type);
GMainContext *main_context = g_main_context_default ();
WriteRequest *wr;
if (self->clipboard == NULL || mime_type == NULL)
{
[item setData:[NSData data] forType:type];
return;
}
wr = g_slice_new0 (WriteRequest);
wr->item = [item retain];
wr->stream = G_MEMORY_OUTPUT_STREAM (g_memory_output_stream_new_resizable ());
wr->type = type;
wr->main_context = g_main_context_ref (main_context);
wr->done = FALSE;
gdk_clipboard_write_async (self->clipboard,
mime_type,
G_OUTPUT_STREAM (wr->stream),
G_PRIORITY_DEFAULT,
self->cancellable,
on_data_ready_cb,
wr);
/* We're forced to provide data synchronously via this API
* so we must block on the main loop. Using another main loop
* than the default tends to get us locked up here, so that is
* what we'll do for now.
*/
while (!wr->done)
g_main_context_iteration (wr->main_context, TRUE);
write_request_free (wr);
}
void
_gdk_macos_clipboard_register_drag_types (NSWindow *window)
{
[window registerForDraggedTypes:[NSArray arrayWithObjects:PTYPE(STRING),
PTYPE(PBOARD),
PTYPE(URL),
PTYPE(FILE_URL),
PTYPE(COLOR),
PTYPE(TIFF),
PTYPE(PNG),
nil]];
}
@end
GdkContentFormats *
_gdk_macos_pasteboard_load_formats (NSPasteboard *pasteboard)
{
return load_offer_formats (pasteboard);
}
void
_gdk_macos_pasteboard_read_async (GObject *object,
NSPasteboard *pasteboard,
GdkContentFormats *formats,
int io_priority,
GCancellable *cancellable,
GAsyncReadyCallback callback,
gpointer user_data)
{
GDK_BEGIN_MACOS_ALLOC_POOL;
GdkContentFormats *offer_formats = NULL;
const char *mime_type;
GInputStream *stream = NULL;
GTask *task = NULL;
g_assert (G_IS_OBJECT (object));
g_assert (pasteboard != NULL);
g_assert (formats != NULL);
task = g_task_new (object, cancellable, callback, user_data);
g_task_set_source_tag (task, _gdk_macos_pasteboard_read_async);
g_task_set_priority (task, io_priority);
offer_formats = load_offer_formats (pasteboard);
mime_type = gdk_content_formats_match_mime_type (formats, offer_formats);
if (mime_type == NULL)
{
g_task_return_new_error (task,
G_IO_ERROR,
G_IO_ERROR_NOT_SUPPORTED,
"%s",
_("No compatible transfer format found"));
goto cleanup;
}
if (strcmp (mime_type, "text/plain;charset=utf-8") == 0)
{
NSString *nsstr = [pasteboard stringForType:NSPasteboardTypeString];
if (nsstr != NULL)
{
const char *str = [nsstr UTF8String];
stream = g_memory_input_stream_new_from_data (g_strdup (str),
strlen (str) + 1,
g_free);
}
}
else if (strcmp (mime_type, "text/uri-list") == 0)
{
G_GNUC_BEGIN_IGNORE_DEPRECATIONS;
if ([[pasteboard types] containsObject:PTYPE(FILE_URL)])
{
GString *str = g_string_new (NULL);
NSArray *files = [pasteboard propertyListForType:NSFilenamesPboardType];
gsize n_files = [files count];
char *data;
guint len;
for (gsize i = 0; i < n_files; ++i)
{
NSString* uriString = [files objectAtIndex:i];
uriString = [@"file://" stringByAppendingString:uriString];
uriString = [uriString stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding];
g_string_append_printf (str,
"%s\r\n",
[uriString cStringUsingEncoding:NSUTF8StringEncoding]);
}
len = str->len;
data = g_string_free (str, FALSE);
stream = g_memory_input_stream_new_from_data (data, len, g_free);
}
G_GNUC_END_IGNORE_DEPRECATIONS;
}
else if (strcmp (mime_type, "application/x-color") == 0)
{
NSColorSpace *colorspace;
NSColor *nscolor;
guint16 color[4];
colorspace = [NSColorSpace genericRGBColorSpace];
nscolor = [[NSColor colorFromPasteboard:pasteboard]
colorUsingColorSpace:colorspace];
color[0] = 0xffff * [nscolor redComponent];
color[1] = 0xffff * [nscolor greenComponent];
color[2] = 0xffff * [nscolor blueComponent];
color[3] = 0xffff * [nscolor alphaComponent];
stream = g_memory_input_stream_new_from_data (g_memdup2 (&color, sizeof color),
sizeof color,
g_free);
}
else if (strcmp (mime_type, "image/tiff") == 0)
{
NSData *data = [pasteboard dataForType:PTYPE(TIFF)];
stream = create_stream_from_nsdata (data);
}
else if (strcmp (mime_type, "image/png") == 0)
{
NSData *data = [pasteboard dataForType:PTYPE(PNG)];
stream = create_stream_from_nsdata (data);
}
if (stream != NULL)
{
g_task_set_task_data (task, g_strdup (mime_type), g_free);
g_task_return_pointer (task, g_steal_pointer (&stream), g_object_unref);
}
else
{
g_task_return_new_error (task,
G_IO_ERROR,
G_IO_ERROR_FAILED,
_("Failed to decode contents with mime-type of '%s'"),
mime_type);
}
cleanup:
g_clear_object (&task);
g_clear_pointer (&offer_formats, gdk_content_formats_unref);
GDK_END_MACOS_ALLOC_POOL;
}
GInputStream *
_gdk_macos_pasteboard_read_finish (GObject *object,
GAsyncResult *result,
const char **out_mime_type,
GError **error)
{
GTask *task = (GTask *)result;
g_assert (G_IS_OBJECT (object));
g_assert (G_IS_TASK (task));
if (out_mime_type != NULL)
*out_mime_type = g_strdup (g_task_get_task_data (task));
return g_task_propagate_pointer (task, error);
}

View File

@@ -155,12 +155,13 @@ void _gdk_macos_display_surface_became_key (GdkMacosDisp
GdkMacosSurface *surface);
void _gdk_macos_display_clear_sorting (GdkMacosDisplay *self);
const GList *_gdk_macos_display_get_surfaces (GdkMacosDisplay *self);
void _gdk_macos_display_send_button_event (GdkMacosDisplay *self,
void _gdk_macos_display_send_event (GdkMacosDisplay *self,
NSEvent *nsevent);
void _gdk_macos_display_warp_pointer (GdkMacosDisplay *self,
int x,
int y);
NSEvent *_gdk_macos_display_get_nsevent (GdkEvent *event);
NSEvent *_gdk_macos_display_get_last_nsevent (void);
GdkDrag *_gdk_macos_display_find_drag (GdkMacosDisplay *self,
NSInteger sequence_number);
GdkDrop *_gdk_macos_display_find_drop (GdkMacosDisplay *self,

View File

@@ -723,6 +723,85 @@ fill_scroll_event (GdkMacosDisplay *self,
return g_steal_pointer (&ret);
}
static GdkEvent *
fill_event (GdkMacosDisplay *self,
GdkMacosWindow *window,
NSEvent *nsevent,
int x,
int y)
{
GdkMacosSurface *surface = [window gdkSurface];
NSEventType event_type = [nsevent type];
GdkEvent *ret = NULL;
switch ((int)event_type)
{
case NSEventTypeLeftMouseDown:
case NSEventTypeRightMouseDown:
case NSEventTypeOtherMouseDown:
case NSEventTypeLeftMouseUp:
case NSEventTypeRightMouseUp:
case NSEventTypeOtherMouseUp:
ret = fill_button_event (self, surface, nsevent, x, y);
break;
case NSEventTypeLeftMouseDragged:
case NSEventTypeRightMouseDragged:
case NSEventTypeOtherMouseDragged:
case NSEventTypeMouseMoved:
ret = fill_motion_event (self, surface, nsevent, x, y);
break;
case NSEventTypeMagnify:
case NSEventTypeRotate:
ret = fill_pinch_event (self, surface, nsevent, x, y);
break;
case NSEventTypeMouseExited:
case NSEventTypeMouseEntered:
{
GdkSeat *seat = gdk_display_get_default_seat (GDK_DISPLAY (self));
GdkDevice *pointer = gdk_seat_get_pointer (seat);
GdkDeviceGrabInfo *grab = _gdk_display_get_last_device_grab (GDK_DISPLAY (self), pointer);
if ([(GdkMacosWindow *)window isInManualResizeOrMove])
{
ret = GDK_MACOS_EVENT_DROP;
}
else if (grab == NULL || grab->owner_events)
{
if (event_type == NSEventTypeMouseExited)
[[NSCursor arrowCursor] set];
ret = synthesize_crossing_event (self, surface, nsevent, x, y);
}
}
break;
case NSEventTypeKeyDown:
case NSEventTypeKeyUp:
case NSEventTypeFlagsChanged: {
GdkEventType type = _gdk_macos_keymap_get_event_type (nsevent);
if (type)
ret = fill_key_event (self, surface, nsevent, type);
break;
}
case NSEventTypeScrollWheel:
ret = fill_scroll_event (self, surface, nsevent, x, y);
break;
default:
break;
}
return ret;
}
static gboolean
is_mouse_button_press_event (NSEventType type)
{
@@ -1025,16 +1104,12 @@ find_surface_for_ns_event (GdkMacosDisplay *self,
GdkMacosBaseView *view;
GdkSurface *surface;
NSPoint point;
int x_tmp;
int y_tmp;
g_assert (GDK_IS_MACOS_DISPLAY (self));
g_assert (nsevent != NULL);
g_assert (x != NULL);
g_assert (y != NULL);
_gdk_macos_display_from_display_coords (self, point.x, point.y, &x_tmp, &y_tmp);
switch ((int)[nsevent type])
{
case NSEventTypeLeftMouseDown:
@@ -1083,7 +1158,6 @@ _gdk_macos_display_translate (GdkMacosDisplay *self,
GdkMacosWindow *window;
NSEventType event_type;
NSWindow *event_window;
GdkEvent *ret = NULL;
int x;
int y;
@@ -1191,79 +1265,15 @@ _gdk_macos_display_translate (GdkMacosDisplay *self,
_gdk_macos_display_clear_sorting (self);
}
}
switch ((int)event_type)
{
case NSEventTypeLeftMouseDown:
case NSEventTypeRightMouseDown:
case NSEventTypeOtherMouseDown:
case NSEventTypeLeftMouseUp:
case NSEventTypeRightMouseUp:
case NSEventTypeOtherMouseUp:
ret = fill_button_event (self, surface, nsevent, x, y);
break;
case NSEventTypeLeftMouseDragged:
case NSEventTypeRightMouseDragged:
case NSEventTypeOtherMouseDragged:
case NSEventTypeMouseMoved:
ret = fill_motion_event (self, surface, nsevent, x, y);
break;
case NSEventTypeMagnify:
case NSEventTypeRotate:
ret = fill_pinch_event (self, surface, nsevent, x, y);
break;
case NSEventTypeMouseExited:
case NSEventTypeMouseEntered:
{
GdkSeat *seat = gdk_display_get_default_seat (GDK_DISPLAY (self));
GdkDevice *pointer = gdk_seat_get_pointer (seat);
GdkDeviceGrabInfo *grab = _gdk_display_get_last_device_grab (GDK_DISPLAY (self), pointer);
if ([(GdkMacosWindow *)window isInManualResizeOrMove])
{
ret = GDK_MACOS_EVENT_DROP;
}
else if (grab == NULL)
{
if (event_type == NSEventTypeMouseExited)
[[NSCursor arrowCursor] set];
ret = synthesize_crossing_event (self, surface, nsevent, x, y);
}
}
break;
case NSEventTypeKeyDown:
case NSEventTypeKeyUp:
case NSEventTypeFlagsChanged: {
GdkEventType type = _gdk_macos_keymap_get_event_type (nsevent);
if (type)
ret = fill_key_event (self, surface, nsevent, type);
break;
}
case NSEventTypeScrollWheel:
ret = fill_scroll_event (self, surface, nsevent, x, y);
break;
default:
break;
}
return ret;
return fill_event (self, window, nsevent, x, y);
}
void
_gdk_macos_display_send_button_event (GdkMacosDisplay *self,
NSEvent *nsevent)
_gdk_macos_display_send_event (GdkMacosDisplay *self,
NSEvent *nsevent)
{
GdkMacosSurface *surface;
GdkMacosWindow *window;
GdkEvent *event;
int x;
int y;
@@ -1272,7 +1282,8 @@ _gdk_macos_display_send_button_event (GdkMacosDisplay *self,
g_return_if_fail (nsevent != NULL);
if ((surface = find_surface_for_ns_event (self, nsevent, &x, &y)) &&
(event = fill_button_event (self, surface, nsevent, x, y)))
(window = (GdkMacosWindow *)_gdk_macos_surface_get_native (surface)) &&
(event = fill_event (self, window, nsevent, x, y)))
_gdk_windowing_got_event (GDK_DISPLAY (self),
_gdk_event_queue_append (GDK_DISPLAY (self), event),
event,

View File

@@ -1024,6 +1024,16 @@ _gdk_macos_display_get_nsevent (GdkEvent *event)
return NULL;
}
NSEvent *
_gdk_macos_display_get_last_nsevent ()
{
const GdkToNSEventMap *map = g_queue_peek_tail (&event_map);
if (map)
return map->nsevent;
return NULL;
}
GdkDrag *
_gdk_macos_display_find_drag (GdkMacosDisplay *self,
NSInteger sequence_number)

View File

@@ -41,7 +41,6 @@ struct _GdkMacosDrag
GdkDrag parent_instance;
GdkMacosDragSurface *drag_surface;
GdkSeat *drag_seat;
GdkCursor *cursor;
int hot_x;
@@ -62,8 +61,22 @@ struct _GdkMacosDragClass
GdkDragClass parent_class;
};
GType gdk_macos_drag_get_type (void) G_GNUC_CONST;
gboolean _gdk_macos_drag_begin (GdkMacosDrag *self);
GType gdk_macos_drag_get_type (void) G_GNUC_CONST;
gboolean _gdk_macos_drag_begin (GdkMacosDrag *self,
GdkContentProvider *content,
GdkMacosWindow *window);
NSDragOperation _gdk_macos_drag_operation (GdkMacosDrag *self);
GdkDragAction _gdk_macos_drag_ns_operation_to_action
(NSDragOperation operation);
void _gdk_macos_drag_surface_move (GdkMacosDrag *self,
int x_root,
int y_root);
void _gdk_macos_drag_set_start_position (GdkMacosDrag *self,
int start_x,
int start_y);
void _gdk_macos_drag_set_actions (GdkMacosDrag *self,
GdkModifierType mods);
G_END_DECLS

View File

@@ -25,6 +25,7 @@
#include "gdkmacoscursor-private.h"
#include "gdkmacosdisplay-private.h"
#include "gdkmacosdragsurface-private.h"
#include "gdkmacospasteboard-private.h"
#include "gdk/gdkdeviceprivate.h"
#include "gdk/gdkeventsprivate.h"
@@ -187,47 +188,6 @@ gdk_macos_drag_set_cursor (GdkDrag *drag,
[nscursor set];
}
static gboolean
drag_grab (GdkMacosDrag *self)
{
GdkSeat *seat;
g_assert (GDK_IS_MACOS_DRAG (self));
seat = gdk_device_get_seat (gdk_drag_get_device (GDK_DRAG (self)));
if (gdk_seat_grab (seat,
GDK_SURFACE (self->drag_surface),
GDK_SEAT_CAPABILITY_ALL_POINTING,
FALSE,
self->cursor,
NULL,
NULL,
NULL) != GDK_GRAB_SUCCESS)
return FALSE;
g_set_object (&self->drag_seat, seat);
return TRUE;
}
static void
drag_ungrab (GdkMacosDrag *self)
{
GdkDisplay *display;
g_assert (GDK_IS_MACOS_DRAG (self));
if (self->drag_seat)
{
gdk_seat_ungrab (self->drag_seat);
g_clear_object (&self->drag_seat);
}
display = gdk_drag_get_display (GDK_DRAG (self));
_gdk_macos_display_break_all_grabs (GDK_MACOS_DISPLAY (display), GDK_CURRENT_TIME);
}
static void
gdk_macos_drag_cancel (GdkDrag *drag,
GdkDragCancelReason reason)
@@ -240,7 +200,6 @@ gdk_macos_drag_cancel (GdkDrag *drag,
return;
self->cancelled = TRUE;
drag_ungrab (self);
gdk_drag_drop_done (drag, FALSE);
}
@@ -253,7 +212,6 @@ gdk_macos_drag_drop_performed (GdkDrag *drag,
g_assert (GDK_IS_MACOS_DRAG (self));
g_object_ref (self);
drag_ungrab (self);
g_signal_emit_by_name (drag, "dnd-finished");
gdk_drag_drop_done (drag, TRUE);
g_object_unref (self);
@@ -316,225 +274,6 @@ gdk_drag_get_current_actions (GdkModifierType state,
}
}
static void
gdk_drag_update (GdkDrag *drag,
double x_root,
double y_root,
GdkModifierType mods,
guint32 evtime)
{
GdkMacosDrag *self = (GdkMacosDrag *)drag;
GdkDragAction suggested_action;
GdkDragAction possible_actions;
g_assert (GDK_IS_MACOS_DRAG (self));
self->last_x = x_root;
self->last_y = y_root;
gdk_drag_get_current_actions (mods,
GDK_BUTTON_PRIMARY,
gdk_drag_get_actions (drag),
&suggested_action,
&possible_actions);
if (GDK_IS_MACOS_SURFACE (self->drag_surface))
_gdk_macos_surface_move (GDK_MACOS_SURFACE (self->drag_surface),
x_root - self->hot_x,
y_root - self->hot_y);
if (!self->did_update)
{
self->start_x = self->last_x;
self->start_y = self->last_y;
self->did_update = TRUE;
}
gdk_drag_set_actions (drag, possible_actions);
}
static gboolean
gdk_dnd_handle_motion_event (GdkDrag *drag,
GdkEvent *event)
{
double x, y;
int x_root, y_root;
g_assert (GDK_IS_MACOS_DRAG (drag));
g_assert (event != NULL);
/* Ignore motion while doing zoomback */
if (GDK_MACOS_DRAG (drag)->cancelled)
return FALSE;
gdk_event_get_position (event, &x, &y);
x_root = event->surface->x + x;
y_root = event->surface->y + y;
gdk_drag_update (drag, x_root, y_root,
gdk_event_get_modifier_state (event),
gdk_event_get_time (event));
return TRUE;
}
static gboolean
gdk_dnd_handle_grab_broken_event (GdkDrag *drag,
GdkEvent *event)
{
GdkMacosDrag *self = GDK_MACOS_DRAG (drag);
gboolean is_implicit = gdk_grab_broken_event_get_implicit (event);
GdkSurface *grab_surface = gdk_grab_broken_event_get_grab_surface (event);
/* Don't cancel if we break the implicit grab from the initial button_press. */
if (is_implicit || grab_surface == (GdkSurface *)self->drag_surface)
return FALSE;
if (gdk_event_get_device (event) != gdk_drag_get_device (drag))
return FALSE;
gdk_drag_cancel (drag, GDK_DRAG_CANCEL_ERROR);
return TRUE;
}
static gboolean
gdk_dnd_handle_button_event (GdkDrag *drag,
GdkEvent *event)
{
GdkMacosDrag *self = GDK_MACOS_DRAG (drag);
g_assert (GDK_IS_MACOS_DRAG (self));
g_assert (event != NULL);
#if 0
/* FIXME: Check the button matches */
if (event->button != self->button)
return FALSE;
#endif
if (gdk_drag_get_selected_action (drag) != 0)
g_signal_emit_by_name (drag, "drop-performed");
else
gdk_drag_cancel (drag, GDK_DRAG_CANCEL_NO_TARGET);
return TRUE;
}
static gboolean
gdk_dnd_handle_key_event (GdkDrag *drag,
GdkEvent *event)
{
GdkMacosDrag *self = GDK_MACOS_DRAG (drag);
GdkModifierType state;
GdkDevice *pointer;
GdkSeat *seat;
int dx, dy;
dx = dy = 0;
state = gdk_event_get_modifier_state (event);
seat = gdk_event_get_seat (event);
pointer = gdk_seat_get_pointer (seat);
if (event->event_type == GDK_KEY_PRESS)
{
guint keyval = gdk_key_event_get_keyval (event);
switch (keyval)
{
case GDK_KEY_Escape:
gdk_drag_cancel (drag, GDK_DRAG_CANCEL_USER_CANCELLED);
return TRUE;
case GDK_KEY_space:
case GDK_KEY_Return:
case GDK_KEY_ISO_Enter:
case GDK_KEY_KP_Enter:
case GDK_KEY_KP_Space:
if (gdk_drag_get_selected_action (drag) != 0)
g_signal_emit_by_name (drag, "drop-performed");
else
gdk_drag_cancel (drag, GDK_DRAG_CANCEL_NO_TARGET);
return TRUE;
case GDK_KEY_Up:
case GDK_KEY_KP_Up:
dy = (state & GDK_ALT_MASK) ? -BIG_STEP : -SMALL_STEP;
break;
case GDK_KEY_Down:
case GDK_KEY_KP_Down:
dy = (state & GDK_ALT_MASK) ? BIG_STEP : SMALL_STEP;
break;
case GDK_KEY_Left:
case GDK_KEY_KP_Left:
dx = (state & GDK_ALT_MASK) ? -BIG_STEP : -SMALL_STEP;
break;
case GDK_KEY_Right:
case GDK_KEY_KP_Right:
dx = (state & GDK_ALT_MASK) ? BIG_STEP : SMALL_STEP;
break;
default:
break;
}
}
/* The state is not yet updated in the event, so we need
* to query it here. We could use XGetModifierMapping, but
* that would be overkill.
*/
gdk_macos_device_query_state (pointer, NULL, NULL, NULL, NULL, &state);
if (dx != 0 || dy != 0)
{
GdkDisplay *display = gdk_event_get_display ((GdkEvent *)event);
self->last_x += dx;
self->last_y += dy;
_gdk_macos_display_warp_pointer (GDK_MACOS_DISPLAY (display),
self->last_x,
self->last_y);
}
gdk_drag_update (drag,
self->last_x, self->last_y,
state,
gdk_event_get_time (event));
return TRUE;
}
static gboolean
gdk_macos_drag_handle_event (GdkDrag *drag,
GdkEvent *event)
{
g_assert (GDK_IS_MACOS_DRAG (drag));
g_assert (event != NULL);
switch ((guint) event->event_type)
{
case GDK_MOTION_NOTIFY:
return gdk_dnd_handle_motion_event (drag, event);
case GDK_BUTTON_RELEASE:
return gdk_dnd_handle_button_event (drag, event);
case GDK_KEY_PRESS:
case GDK_KEY_RELEASE:
return gdk_dnd_handle_key_event (drag, event);
case GDK_GRAB_BROKEN:
return gdk_dnd_handle_grab_broken_event (drag, event);
default:
return FALSE;
}
}
static void
gdk_macos_drag_finalize (GObject *object)
{
@@ -542,11 +281,6 @@ gdk_macos_drag_finalize (GObject *object)
GdkMacosDragSurface *drag_surface = g_steal_pointer (&self->drag_surface);
g_clear_object (&self->cursor);
if (self->drag_seat)
{
gdk_seat_ungrab (self->drag_seat);
g_clear_object (&self->drag_seat);
}
G_OBJECT_CLASS (gdk_macos_drag_parent_class)->finalize (object);
@@ -608,7 +342,6 @@ gdk_macos_drag_class_init (GdkMacosDragClass *klass)
drag_class->set_cursor = gdk_macos_drag_set_cursor;
drag_class->cancel = gdk_macos_drag_cancel;
drag_class->drop_performed = gdk_macos_drag_drop_performed;
drag_class->handle_event = gdk_macos_drag_handle_event;
properties [PROP_DRAG_SURFACE] =
g_param_spec_object ("drag-surface", NULL, NULL,
@@ -624,11 +357,113 @@ gdk_macos_drag_init (GdkMacosDrag *self)
}
gboolean
_gdk_macos_drag_begin (GdkMacosDrag *self)
_gdk_macos_drag_begin (GdkMacosDrag *self,
GdkContentProvider *content,
GdkMacosWindow *window)
{
NSArray<NSDraggingItem *> *items;
NSDraggingSession *session;
NSPasteboardItem *item;
NSEvent *nsevent;
g_return_val_if_fail (GDK_IS_MACOS_DRAG (self), FALSE);
g_return_val_if_fail (GDK_IS_MACOS_WINDOW (window), FALSE);
_gdk_macos_surface_show (GDK_MACOS_SURFACE (self->drag_surface));
GDK_BEGIN_MACOS_ALLOC_POOL;
return drag_grab (self);
item = [[GdkMacosPasteboardItem alloc] initForDrag:GDK_DRAG (self) withContentProvider:content];
items = [NSArray arrayWithObject:item];
nsevent = _gdk_macos_display_get_last_nsevent ();
session = [[window contentView] beginDraggingSessionWithItems:items
event:nsevent
source:window];
GDK_END_MACOS_ALLOC_POOL;
_gdk_macos_display_set_drag (GDK_MACOS_DISPLAY (gdk_drag_get_display (GDK_DRAG (self))),
[session draggingSequenceNumber],
GDK_DRAG (self));
return TRUE;
}
NSDragOperation
_gdk_macos_drag_operation (GdkMacosDrag *self)
{
NSDragOperation operation = NSDragOperationNone;
GdkDragAction actions;
g_return_val_if_fail (GDK_IS_MACOS_DRAG (self), NSDragOperationNone);
actions = gdk_drag_get_actions (GDK_DRAG (self));
if (actions & GDK_ACTION_LINK)
operation |= NSDragOperationLink;
if (actions & GDK_ACTION_MOVE)
operation |= NSDragOperationMove;
if (actions & GDK_ACTION_COPY)
operation |= NSDragOperationCopy;
return operation;
}
GdkDragAction
_gdk_macos_drag_ns_operation_to_action (NSDragOperation operation)
{
if (operation & NSDragOperationCopy)
return GDK_ACTION_COPY;
if (operation & NSDragOperationMove)
return GDK_ACTION_MOVE;
if (operation & NSDragOperationLink)
return GDK_ACTION_LINK;
return 0;
}
void
_gdk_macos_drag_surface_move (GdkMacosDrag *self,
int x_root,
int y_root)
{
g_return_if_fail (GDK_IS_MACOS_DRAG (self));
self->last_x = x_root;
self->last_y = y_root;
if (GDK_IS_MACOS_SURFACE (self->drag_surface))
_gdk_macos_surface_move (GDK_MACOS_SURFACE (self->drag_surface),
x_root - self->hot_x,
y_root - self->hot_y);
}
void
_gdk_macos_drag_set_start_position (GdkMacosDrag *self,
int start_x,
int start_y)
{
g_return_if_fail (GDK_IS_MACOS_DRAG (self));
self->start_x = start_x;
self->start_y = start_y;
}
void
_gdk_macos_drag_set_actions (GdkMacosDrag *self,
GdkModifierType mods)
{
GdkDragAction suggested_action;
GdkDragAction possible_actions;
g_assert (GDK_IS_MACOS_DRAG (self));
gdk_drag_get_current_actions (mods,
GDK_BUTTON_PRIMARY,
gdk_drag_get_actions (GDK_DRAG (self)),
&suggested_action,
&possible_actions);
gdk_drag_set_selected_action (GDK_DRAG (self), suggested_action);
gdk_drag_set_actions (GDK_DRAG (self), possible_actions);
}

View File

@@ -37,11 +37,15 @@
/*
* This file implementations integration between the GLib main loop and
* the native system of the Core Foundation run loop and Cocoa event
* handling. There are basically two different cases that we need to
* handle: either the GLib main loop is in control (the application
* has called gtk_main(), or is otherwise iterating the main loop), or
* CFRunLoop is in control (we are in a modal operation such as window
* resizing or drag-and-drop.)
* handling. There are basically three different cases that we need to
* handle:
*
* - the GLib main loop is in control. The application has called
* gtk_main(), or is otherwise iterating the main loop.
* - CFRunLoop is in control. We are in a modal operation such as window
* resizing.
* - CFRunLoop is running a nested loop. This happens when a drag-and-drop
* operation has been initiated.
*
* When the GLib main loop is in control we integrate in native event
* handling in two ways: first we add a GSource that handles checking
@@ -57,14 +61,23 @@
* stages of the GLib main loop (prepare, check, dispatch), and make the
* appropriate calls into GLib.
*
* Both cases share a single problem: the OS X APIs dont allow us to
* When initiating a drag operation, a nested CFRunLoop is executed.
* The nested run loop is started when fetching a native event in our GLib
* main loop. The application does not receive any events until the nested loop
* is finished. We work around this by forwarding the
* events that trigger the callbacks of the NSDraggingSource protocol.
* The "run loop observer" is executing the GLib main loop stages as long as we're
* in the nested run loop, as if CFRunLoop were in control.
* See also GdkMacosWindow.
*
* All cases share a single problem: the macOS APIs dont allow us to
* wait simultaneously for file descriptors and for events. So when we
* need to do a blocking wait that includes file descriptor activity, we
* push the actual work of calling select() to a helper thread (the
* "select thread") and wait for native events in the main thread.
*
* The main known limitation of this code is that if a callback is triggered
* via the OS X run loop while we are "polling" (in either case described
* via the macOS run loop while we are "polling" (in either case described
* above), iteration of the GLib main loop is not possible from within
* that callback. If the programmer tries to do so explicitly, then they
* will get a warning from GLib "main loop already active in another thread".
@@ -640,6 +653,23 @@ _gdk_macos_event_source_get_pending (void)
return event;
}
static void
_gdk_macos_event_source_queue_event (NSEvent *event)
{
/* Just used to wake us up; if an event and a FD arrived at the same
* time; could have come from a previous iteration in some cases,
* but the spurious wake up is harmless if a little inefficient.
*/
if (!event ||
([event type] == NSEventTypeApplicationDefined &&
[event subtype] == GDK_MACOS_EVENT_SUBTYPE_EVENTLOOP))
return;
if (!current_events)
current_events = g_queue_new ();
g_queue_push_head (current_events, [event retain]);
}
static gboolean
gdk_macos_event_source_prepare (GSource *source,
int *timeout)
@@ -782,23 +812,7 @@ poll_func (GPollFD *ufds,
if (last_ufds == ufds && n_ready < 0)
n_ready = select_thread_collect_poll (ufds, nfds);
if (event &&
[event type] == NSEventTypeApplicationDefined &&
[event subtype] == GDK_MACOS_EVENT_SUBTYPE_EVENTLOOP)
{
/* Just used to wake us up; if an event and a FD arrived at the same
* time; could have come from a previous iteration in some cases,
* but the spurious wake up is harmless if a little inefficient.
*/
event = NULL;
}
if (event)
{
if (!current_events)
current_events = g_queue_new ();
g_queue_push_head (current_events, [event retain]);
}
_gdk_macos_event_source_queue_event (event);
return n_ready;
}
@@ -1018,7 +1032,10 @@ run_loop_observer_callback (CFRunLoopObserverRef observer,
break;
}
if (getting_events > 0) /* Activity we triggered */
/* DnD starts a nested runloop, or so it seems.
If we have such a loop, we still want to run
our idle handlers. */
if (getting_events > 0 && current_loop_level < 2)
return;
switch (activity)
@@ -1042,7 +1059,6 @@ run_loop_observer_callback (CFRunLoopObserverRef observer,
run_loop_exit ();
break;
case kCFRunLoopAllActivities:
/* TODO: Do most of the above? */
default:
break;
}

View File

@@ -0,0 +1,74 @@
/*
* Copyright © 2021 Red Hat, Inc.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library 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
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
*
* SPDX-License-Identifier: LGPL-2.1-or-later
*/
#ifndef __GDK_MACOS_PASTEBOARD_PRIVATE_H__
#define __GDK_MACOS_PASTEBOARD_PRIVATE_H__
#include <AppKit/AppKit.h>
#include <gio/gio.h>
#include "gdkclipboardprivate.h"
G_BEGIN_DECLS
@interface GdkMacosPasteboardItemDataProvider : NSObject <NSPasteboardItemDataProvider>
{
GdkContentProvider *_contentProvider;
GdkClipboard *_clipboard;
GdkDrag *_drag;
}
-(id)initForClipboard:(GdkClipboard *)clipboard withContentProvider:(GdkContentProvider *)contentProvider;
-(id)initForDrag:(GdkDrag *)drag withContentProvider:(GdkContentProvider *)contentProvider;
@end
@interface GdkMacosPasteboardItem : NSPasteboardItem
{
GdkContentProvider *_contentProvider;
GdkClipboard *_clipboard;
GdkDrag *_drag;
NSRect _draggingFrame;
}
-(id)initForClipboard:(GdkClipboard *)clipboard withContentProvider:(GdkContentProvider *)contentProvider;
-(id)initForDrag:(GdkDrag *)drag withContentProvider:(GdkContentProvider *)contentProvider;
@end
NSPasteboardType _gdk_macos_pasteboard_to_ns_type (const char *mime_type,
NSPasteboardType *alternate);
const char *_gdk_macos_pasteboard_from_ns_type (NSPasteboardType type);
GdkContentFormats *_gdk_macos_pasteboard_load_formats (NSPasteboard *pasteboard);
void _gdk_macos_pasteboard_register_drag_types (NSWindow *window);
void _gdk_macos_pasteboard_read_async (GObject *object,
NSPasteboard *pasteboard,
GdkContentFormats *formats,
int io_priority,
GCancellable *cancellable,
GAsyncReadyCallback callback,
gpointer user_data);
GInputStream *_gdk_macos_pasteboard_read_finish (GObject *object,
GAsyncResult *result,
const char **out_mime_type,
GError **error);
G_END_DECLS
#endif /* __GDK_MACOS_PASTEBOARD_PRIVATE_H__ */

View File

@@ -0,0 +1,602 @@
/*
* Copyright © 2021 Red Hat, Inc.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library 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
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
*
* SPDX-License-Identifier: LGPL-2.1-or-later
*/
#include "config.h"
#include <glib/gi18n.h>
#include "gdkdragprivate.h"
#include "gdkmacospasteboard-private.h"
#include "gdkmacosutils-private.h"
enum {
TYPE_STRING,
TYPE_PBOARD,
TYPE_URL,
TYPE_FILE_URL,
TYPE_COLOR,
TYPE_TIFF,
TYPE_PNG,
TYPE_LAST
};
#define PTYPE(k) (get_pasteboard_type(TYPE_##k))
static NSPasteboardType pasteboard_types[TYPE_LAST];
static NSPasteboardType
get_pasteboard_type (int type)
{
static gsize initialized = FALSE;
g_assert (type >= 0);
g_assert (type < TYPE_LAST);
if (g_once_init_enter (&initialized))
{
pasteboard_types[TYPE_PNG] = NSPasteboardTypePNG;
pasteboard_types[TYPE_STRING] = NSPasteboardTypeString;
pasteboard_types[TYPE_TIFF] = NSPasteboardTypeTIFF;
pasteboard_types[TYPE_COLOR] = NSPasteboardTypeColor;
G_GNUC_BEGIN_IGNORE_DEPRECATIONS
pasteboard_types[TYPE_PBOARD] = NSStringPboardType;
G_GNUC_END_IGNORE_DEPRECATIONS
#ifdef AVAILABLE_MAC_OS_X_VERSION_10_13_AND_LATER
pasteboard_types[TYPE_URL] = NSPasteboardTypeURL;
pasteboard_types[TYPE_FILE_URL] = NSPasteboardTypeFileURL;
#else
pasteboard_types[TYPE_URL] = [[NSString alloc] initWithUTF8String:"public.url"];
pasteboard_types[TYPE_FILE_URL] = [[NSString alloc] initWithUTF8String:"public.file-url"];
#endif
g_once_init_leave (&initialized, TRUE);
}
return pasteboard_types[type];
}
const char *
_gdk_macos_pasteboard_from_ns_type (NSPasteboardType type)
{
G_GNUC_BEGIN_IGNORE_DEPRECATIONS;
if ([type isEqualToString:PTYPE(STRING)] ||
[type isEqualToString:PTYPE(PBOARD)])
return g_intern_string ("text/plain;charset=utf-8");
else if ([type isEqualToString:PTYPE(URL)] ||
[type isEqualToString:PTYPE(FILE_URL)])
return g_intern_string ("text/uri-list");
else if ([type isEqualToString:PTYPE(COLOR)])
return g_intern_string ("application/x-color");
else if ([type isEqualToString:PTYPE(TIFF)])
return g_intern_string ("image/tiff");
else if ([type isEqualToString:PTYPE(PNG)])
return g_intern_string ("image/png");
G_GNUC_END_IGNORE_DEPRECATIONS;
return NULL;
}
NSPasteboardType
_gdk_macos_pasteboard_to_ns_type (const char *mime_type,
NSPasteboardType *alternate)
{
if (alternate)
*alternate = NULL;
if (g_strcmp0 (mime_type, "text/plain;charset=utf-8") == 0)
{
return PTYPE(STRING);
}
else if (g_strcmp0 (mime_type, "text/uri-list") == 0)
{
if (alternate)
*alternate = PTYPE(URL);
return PTYPE(FILE_URL);
}
else if (g_strcmp0 (mime_type, "application/x-color") == 0)
{
return PTYPE(COLOR);
}
else if (g_strcmp0 (mime_type, "image/tiff") == 0)
{
return PTYPE(TIFF);
}
else if (g_strcmp0 (mime_type, "image/png") == 0)
{
return PTYPE(PNG);
}
return nil;
}
static void
populate_content_formats (GdkContentFormatsBuilder *builder,
NSPasteboardType type)
{
const char *mime_type;
g_assert (builder != NULL);
g_assert (type != NULL);
if ((mime_type = _gdk_macos_pasteboard_from_ns_type (type)))
gdk_content_formats_builder_add_mime_type (builder, mime_type);
}
static GdkContentFormats *
load_offer_formats (NSPasteboard *pasteboard)
{
GDK_BEGIN_MACOS_ALLOC_POOL;
GdkContentFormatsBuilder *builder;
GdkContentFormats *formats;
builder = gdk_content_formats_builder_new ();
for (NSPasteboardType type in [pasteboard types])
populate_content_formats (builder, type);
formats = gdk_content_formats_builder_free_to_formats (builder);
GDK_END_MACOS_ALLOC_POOL;
return g_steal_pointer (&formats);
}
GdkContentFormats *
_gdk_macos_pasteboard_load_formats (NSPasteboard *pasteboard)
{
return load_offer_formats (pasteboard);
}
static GInputStream *
create_stream_from_nsdata (NSData *data)
{
const guint8 *bytes = [data bytes];
gsize len = [data length];
return g_memory_input_stream_new_from_data (g_memdup2 (bytes, len), len, g_free);
}
void
_gdk_macos_pasteboard_read_async (GObject *object,
NSPasteboard *pasteboard,
GdkContentFormats *formats,
int io_priority,
GCancellable *cancellable,
GAsyncReadyCallback callback,
gpointer user_data)
{
GDK_BEGIN_MACOS_ALLOC_POOL;
GdkContentFormats *offer_formats = NULL;
const char *mime_type;
GInputStream *stream = NULL;
GTask *task = NULL;
g_assert (G_IS_OBJECT (object));
g_assert (pasteboard != NULL);
g_assert (formats != NULL);
task = g_task_new (object, cancellable, callback, user_data);
g_task_set_source_tag (task, _gdk_macos_pasteboard_read_async);
g_task_set_priority (task, io_priority);
offer_formats = load_offer_formats (pasteboard);
mime_type = gdk_content_formats_match_mime_type (formats, offer_formats);
if (mime_type == NULL)
{
g_task_return_new_error (task,
G_IO_ERROR,
G_IO_ERROR_NOT_SUPPORTED,
"%s",
_("No compatible transfer format found"));
goto cleanup;
}
if (strcmp (mime_type, "text/plain;charset=utf-8") == 0)
{
NSString *nsstr = [pasteboard stringForType:NSPasteboardTypeString];
if (nsstr != NULL)
{
const char *str = [nsstr UTF8String];
stream = g_memory_input_stream_new_from_data (g_strdup (str),
strlen (str) + 1,
g_free);
}
}
else if (strcmp (mime_type, "text/uri-list") == 0)
{
G_GNUC_BEGIN_IGNORE_DEPRECATIONS;
if ([[pasteboard types] containsObject:PTYPE(FILE_URL)])
{
GString *str = g_string_new (NULL);
NSArray *files = [pasteboard propertyListForType:NSFilenamesPboardType];
gsize n_files = [files count];
char *data;
guint len;
for (gsize i = 0; i < n_files; ++i)
{
NSString* uriString = [files objectAtIndex:i];
uriString = [@"file://" stringByAppendingString:uriString];
uriString = [uriString stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding];
g_string_append_printf (str,
"%s\r\n",
[uriString cStringUsingEncoding:NSUTF8StringEncoding]);
}
len = str->len;
data = g_string_free (str, FALSE);
stream = g_memory_input_stream_new_from_data (data, len, g_free);
}
G_GNUC_END_IGNORE_DEPRECATIONS;
}
else if (strcmp (mime_type, "application/x-color") == 0)
{
NSColorSpace *colorspace;
NSColor *nscolor;
guint16 color[4];
colorspace = [NSColorSpace genericRGBColorSpace];
nscolor = [[NSColor colorFromPasteboard:pasteboard]
colorUsingColorSpace:colorspace];
color[0] = 0xffff * [nscolor redComponent];
color[1] = 0xffff * [nscolor greenComponent];
color[2] = 0xffff * [nscolor blueComponent];
color[3] = 0xffff * [nscolor alphaComponent];
stream = g_memory_input_stream_new_from_data (g_memdup2 (&color, sizeof color),
sizeof color,
g_free);
}
else if (strcmp (mime_type, "image/tiff") == 0)
{
NSData *data = [pasteboard dataForType:PTYPE(TIFF)];
stream = create_stream_from_nsdata (data);
}
else if (strcmp (mime_type, "image/png") == 0)
{
NSData *data = [pasteboard dataForType:PTYPE(PNG)];
stream = create_stream_from_nsdata (data);
}
if (stream != NULL)
{
g_task_set_task_data (task, g_strdup (mime_type), g_free);
g_task_return_pointer (task, g_steal_pointer (&stream), g_object_unref);
}
else
{
g_task_return_new_error (task,
G_IO_ERROR,
G_IO_ERROR_FAILED,
_("Failed to decode contents with mime-type of '%s'"),
mime_type);
}
cleanup:
g_clear_object (&task);
g_clear_pointer (&offer_formats, gdk_content_formats_unref);
GDK_END_MACOS_ALLOC_POOL;
}
GInputStream *
_gdk_macos_pasteboard_read_finish (GObject *object,
GAsyncResult *result,
const char **out_mime_type,
GError **error)
{
GTask *task = (GTask *)result;
g_assert (G_IS_OBJECT (object));
g_assert (G_IS_TASK (task));
if (out_mime_type != NULL)
*out_mime_type = g_strdup (g_task_get_task_data (task));
return g_task_propagate_pointer (task, error);
}
void
_gdk_macos_pasteboard_register_drag_types (NSWindow *window)
{
[window registerForDraggedTypes:[NSArray arrayWithObjects:PTYPE(STRING),
PTYPE(PBOARD),
PTYPE(URL),
PTYPE(FILE_URL),
PTYPE(COLOR),
PTYPE(TIFF),
PTYPE(PNG),
nil]];
}
@implementation GdkMacosPasteboardItemDataProvider
-(id)initForClipboard:(GdkClipboard*)clipboard withContentProvider:(GdkContentProvider*)contentProvider
{
[super init];
g_set_object (&self->_clipboard, clipboard);
g_set_object (&self->_contentProvider, contentProvider);
return self;
}
-(id)initForDrag:(GdkDrag*)drag withContentProvider:(GdkContentProvider*)contentProvider
{
[super init];
g_set_object (&self->_drag, drag);
g_set_object (&self->_contentProvider, contentProvider);
return self;
}
-(void)dealloc
{
g_clear_object (&self->_contentProvider);
g_clear_object (&self->_clipboard);
g_clear_object (&self->_drag);
[super dealloc];
}
-(NSArray<NSPasteboardType> *)types
{
NSMutableArray *ret = [[NSMutableArray alloc] init];
GdkContentFormats *serializable;
const char * const *mime_types;
gsize n_mime_types;
serializable = gdk_content_provider_ref_storable_formats (self->_contentProvider);
serializable = gdk_content_formats_union_serialize_mime_types (serializable);
mime_types = gdk_content_formats_get_mime_types (serializable, &n_mime_types);
for (gsize i = 0; i < n_mime_types; i++)
{
const char *mime_type = mime_types[i];
NSPasteboardType type;
NSPasteboardType alternate = nil;
if ((type = _gdk_macos_pasteboard_to_ns_type (mime_type, &alternate)))
{
[ret addObject:type];
if (alternate)
[ret addObject:alternate];
}
}
gdk_content_formats_unref (serializable);
/* Default to an url type (think gobject://internal)
* to support internal, GType-based DnD.
*/
if (n_mime_types == 0)
{
GdkContentFormats *formats;
gsize n_gtypes;
formats = gdk_content_provider_ref_formats (self->_contentProvider);
gdk_content_formats_get_gtypes (formats, &n_gtypes);
if (n_gtypes)
[ret addObject:NSPasteboardTypeURL];
gdk_content_formats_unref (formats);
}
return g_steal_pointer (&ret);
}
typedef struct
{
GMemoryOutputStream *stream;
NSPasteboardItem *item;
NSPasteboardType type;
GMainContext *main_context;
guint done : 1;
} WriteRequest;
static void
write_request_free (WriteRequest *wr)
{
g_clear_pointer (&wr->main_context, g_main_context_unref);
g_clear_object (&wr->stream);
[wr->item release];
g_slice_free (WriteRequest, wr);
}
static void
on_data_ready_cb (GObject *object,
GAsyncResult *result,
gpointer user_data)
{
GDK_BEGIN_MACOS_ALLOC_POOL;
WriteRequest *wr = user_data;
GError *error = NULL;
NSData *data = nil;
gboolean ret;
g_assert (G_IS_OBJECT (object));
g_assert (GDK_IS_CLIPBOARD (object) || GDK_IS_DRAG (object));
g_assert (G_IS_ASYNC_RESULT (result));
g_assert (wr != NULL);
g_assert (G_IS_MEMORY_OUTPUT_STREAM (wr->stream));
g_assert ([wr->item isKindOfClass:[NSPasteboardItem class]]);
if (GDK_IS_CLIPBOARD (object))
ret = gdk_clipboard_write_finish (GDK_CLIPBOARD (object), result, &error);
else if (GDK_IS_DRAG (object))
ret = gdk_drag_write_finish (GDK_DRAG (object), result, &error);
else
g_return_if_reached ();
if (ret)
{
gsize size;
gpointer bytes;
g_output_stream_close (G_OUTPUT_STREAM (wr->stream), NULL, NULL);
size = g_memory_output_stream_get_data_size (wr->stream);
bytes = g_memory_output_stream_steal_data (wr->stream);
data = [[NSData alloc] initWithBytesNoCopy:bytes
length:size
deallocator:^(void *alloc, NSUInteger length) { g_free (alloc); }];
}
else
{
g_warning ("Failed to serialize pasteboard contents: %s",
error->message);
g_clear_error (&error);
}
[wr->item setData:data forType:wr->type];
wr->done = TRUE;
GDK_END_MACOS_ALLOC_POOL;
}
-(void)pasteboard:(NSPasteboard *)pasteboard item:(NSPasteboardItem *)item provideDataForType:(NSPasteboardType)type
{
const char *mime_type = _gdk_macos_pasteboard_from_ns_type (type);
GMainContext *main_context = g_main_context_default ();
WriteRequest *wr;
if (self->_contentProvider == NULL || mime_type == NULL)
{
[item setData:[NSData data] forType:type];
return;
}
wr = g_slice_new0 (WriteRequest);
wr->item = [item retain];
wr->stream = G_MEMORY_OUTPUT_STREAM (g_memory_output_stream_new_resizable ());
wr->type = type;
wr->main_context = g_main_context_ref (main_context);
wr->done = FALSE;
if (GDK_IS_CLIPBOARD (self->_clipboard))
gdk_clipboard_write_async (self->_clipboard,
mime_type,
G_OUTPUT_STREAM (wr->stream),
G_PRIORITY_DEFAULT,
NULL,
on_data_ready_cb,
wr);
else if (GDK_IS_DRAG (self->_drag))
gdk_drag_write_async (self->_drag,
mime_type,
G_OUTPUT_STREAM (wr->stream),
G_PRIORITY_DEFAULT,
NULL,
on_data_ready_cb,
wr);
else
g_return_if_reached ();
/* We're forced to provide data synchronously via this API
* so we must block on the main loop. Using another main loop
* than the default tends to get us locked up here, so that is
* what we'll do for now.
*/
while (!wr->done)
g_main_context_iteration (wr->main_context, TRUE);
write_request_free (wr);
}
-(void)pasteboardFinishedWithDataProvider:(NSPasteboard *)pasteboard
{
g_clear_object (&self->_clipboard);
g_clear_object (&self->_drag);
g_clear_object (&self->_contentProvider);
}
@end
@implementation GdkMacosPasteboardItem
-(id)initForClipboard:(GdkClipboard*)clipboard withContentProvider:(GdkContentProvider*)contentProvider
{
GdkMacosPasteboardItemDataProvider *dataProvider;
dataProvider = [[GdkMacosPasteboardItemDataProvider alloc] initForClipboard:clipboard withContentProvider:contentProvider];
[super init];
g_set_object (&self->_clipboard, clipboard);
g_set_object (&self->_contentProvider, contentProvider);
[self setDataProvider:dataProvider forTypes:[dataProvider types]];
[dataProvider release];
return self;
}
-(id)initForDrag:(GdkDrag*)drag withContentProvider:(GdkContentProvider*)contentProvider
{
GdkMacosPasteboardItemDataProvider *dataProvider;
dataProvider = [[GdkMacosPasteboardItemDataProvider alloc] initForDrag:drag withContentProvider:contentProvider];
[super init];
g_set_object (&self->_drag, drag);
g_set_object (&self->_contentProvider, contentProvider);
[self setDataProvider:dataProvider forTypes:[dataProvider types]];
[dataProvider release];
return self;
}
-(void)dealloc
{
g_clear_object (&self->_contentProvider);
g_clear_object (&self->_clipboard);
g_clear_object (&self->_drag);
[super dealloc];
}
-(NSRect)draggingFrame
{
return self->_draggingFrame;
}
-(void)setDraggingFrame:(NSRect)draggingFrame;
{
self->_draggingFrame = draggingFrame;
}
-(id)item
{
return self;
}
-(NSArray* (^) (void))imageComponentsProvider
{
return nil;
}
@end

View File

@@ -446,7 +446,7 @@ gdk_macos_surface_drag_begin (GdkSurface *surface,
gdk_drag_get_selected_action (GDK_DRAG (drag)));
gdk_drag_set_cursor (GDK_DRAG (drag), cursor);
if (!_gdk_macos_drag_begin (drag))
if (!_gdk_macos_drag_begin (drag, content, self->window))
{
g_object_unref (drag);
return NULL;

View File

@@ -19,6 +19,7 @@ gdk_macos_sources = files([
'gdkmacoseventsource.c',
'gdkmacoskeymap.c',
'gdkmacosmonitor.c',
'gdkmacospasteboard.c',
'gdkmacospopupsurface.c',
'gdkmacosseat.c',
'gdkmacossurface.c',

View File

@@ -104,7 +104,9 @@ gtk_application_impl_wayland_before_emit (GtkApplicationImpl *impl,
{
const char *startup_notification_id = NULL;
g_variant_lookup (platform_data, "desktop-startup-id", "&s", &startup_notification_id);
g_variant_lookup (platform_data, "activation-token", "&s", &startup_notification_id);
if (!startup_notification_id)
g_variant_lookup (platform_data, "desktop-startup-id", "&s", &startup_notification_id);
gdk_wayland_display_set_startup_notification_id (gdk_display_get_default (), startup_notification_id);
}

View File

@@ -323,8 +323,12 @@ gtk_application_add_platform_data (GApplication *application,
startup_id = gdk_display_get_startup_notification_id (display);
if (startup_id && g_utf8_validate (startup_id, -1, NULL))
g_variant_builder_add (builder, "{sv}", "desktop-startup-id",
g_variant_new_string (startup_id));
{
g_variant_builder_add (builder, "{sv}", "activation-token",
g_variant_new_string (startup_id));
g_variant_builder_add (builder, "{sv}", "desktop-startup-id",
g_variant_new_string (startup_id));
}
}
}

View File

@@ -1086,10 +1086,8 @@ gtk_css_provider_load_internal (GtkCssProvider *self,
/**
* gtk_css_provider_load_from_data:
* @css_provider: a `GtkCssProvider`
* @data: (array length=length) (element-type guint8): CSS data loaded in memory
* @length: the length of @data in bytes, or -1 for NUL terminated strings. If
* @length is not -1, the code will assume it is not NUL terminated and will
* potentially do a copy.
* @data: CSS data to be parsed
* @length: the length of @data in bytes, or -1 for NUL terminated strings
*
* Loads @data into @css_provider.
*

View File

@@ -569,7 +569,7 @@ gtk_drag_source_drag_begin (GtkDragSource *source)
GtkNative *native;
GdkSurface *surface;
double px, py;
int dx, dy;
double dx, dy;
GdkContentProvider *content = NULL;
widget = gtk_event_controller_get_widget (GTK_EVENT_CONTROLLER (source));

View File

@@ -33,6 +33,7 @@
#include "gtksnapshot.h"
#include "gtkwidgetprivate.h"
#include "gdk/gdkprofilerprivate.h"
#include "gtksymbolicpaintable.h"
struct _GtkIconHelper
{
@@ -123,7 +124,7 @@ gtk_icon_helper_load_paintable (GtkIconHelper *self,
{
case GTK_IMAGE_PAINTABLE:
paintable = g_object_ref (gtk_image_definition_get_paintable (self->def));
symbolic = FALSE;
symbolic = GTK_IS_SYMBOLIC_PAINTABLE (paintable);
break;
case GTK_IMAGE_ICON_NAME:

View File

@@ -1222,6 +1222,10 @@ captured_scroll_cb (GtkEventControllerScroll *scroll,
gtk_scrolled_window_cancel_deceleration (scrolled_window);
if (!may_hscroll (scrolled_window) &&
!may_vscroll (scrolled_window))
return GDK_EVENT_PROPAGATE;
if (priv->smooth_scroll)
{
scrolled_window_scroll (scrolled_window, delta_x, delta_y, scroll);
@@ -1412,6 +1416,10 @@ scroll_controller_scroll (GtkEventControllerScroll *scroll,
GtkScrolledWindowPrivate *priv =
gtk_scrolled_window_get_instance_private (scrolled_window);
if (!may_hscroll (scrolled_window) &&
!may_vscroll (scrolled_window))
return GDK_EVENT_PROPAGATE;
if (!priv->smooth_scroll)
scrolled_window_scroll (scrolled_window, delta_x, delta_y, scroll);

View File

@@ -742,9 +742,8 @@ gtk_switch_get_active (GtkSwitch *self)
*
* Sets the underlying state of the `GtkSwitch`.
*
* Normally, this is the same as [property@Gtk.Switch:active], unless
* the switch is set up for delayed state changes. This function is
* typically called from a [signal@Gtk.Switch::state-set] signal handler.
* This function is typically called from a [signal@Gtk.Switch::state-set]
* signal handler in order to set up delayed state changes.
*
* See [signal@Gtk.Switch::state-set] for details.
*/
@@ -761,12 +760,6 @@ gtk_switch_set_state (GtkSwitch *self,
self->state = state;
/* This will be a no-op if we're switching the state in response
* to a UI change. We're setting active anyway, to catch 'spontaneous'
* state changes.
*/
gtk_switch_set_active (self, state);
if (state)
gtk_widget_set_state_flags (GTK_WIDGET (self), GTK_STATE_FLAG_CHECKED, FALSE);
else

View File

@@ -66,8 +66,6 @@ struct _GtkTooltipWindowClass
GtkWidgetClass parent_class;
};
#define CHARS_WRAP_LIMIT 50
static void gtk_tooltip_window_native_init (GtkNativeInterface *iface);
G_DEFINE_TYPE_WITH_CODE (GtkTooltipWindow, gtk_tooltip_window, GTK_TYPE_WIDGET,
@@ -415,14 +413,7 @@ update_label_width (GtkLabel *label)
}
else
{
int len;
len = g_utf8_strlen (text, -1);
if (len > CHARS_WRAP_LIMIT)
gtk_label_set_width_chars (label, CHARS_WRAP_LIMIT);
gtk_label_set_max_width_chars (label, MIN (len, CHARS_WRAP_LIMIT));
gtk_label_set_max_width_chars (label, 50);
gtk_label_set_wrap (label, TRUE);
}
}

View File

@@ -1002,7 +1002,6 @@ bind_type_cb (GtkSignalListItemFactory *factory,
expander = gtk_list_item_get_child (list_item);
gtk_tree_expander_set_list_row (GTK_TREE_EXPANDER (expander), list_row);
item = gtk_tree_list_row_get_item (list_row);
expander = gtk_list_item_get_child (list_item);
inscription = gtk_tree_expander_get_child (GTK_TREE_EXPANDER (expander));
gtk_inscription_set_text (GTK_INSCRIPTION (inscription), G_OBJECT_TYPE_NAME (item));

View File

@@ -13,6 +13,7 @@
</child>
<child>
<object class="GtkLabel" id="label">
<property name="hexpand">1</property>
<property name="wrap">1</property>
</object>
</child>

View File

@@ -29,6 +29,7 @@ gdk/loaders/gdktiff.c
gdk/macos/gdkmacosclipboard.c
gdk/macos/gdkmacosdrag.c
gdk/macos/gdkmacosglcontext.c
gdk/macos/gdkmacospasteboard.c
gdk/wayland/gdkclipboard-wayland.c
gdk/wayland/gdkdrag-wayland.c
gdk/wayland/gdkdrop-wayland.c

166
po/he.po
View File

@@ -6,14 +6,14 @@
# Gil Osher <dolfin@rpg.org.il>, 2004.
# Yair Hershkovitz <yairhr@gmail.com>, 2006.
# Yaron Shahrabani <sh.yaron@gmail.com>, 2011, 2012.
# Yosef Or Boczko <yoseforb@gmail.com>, 2013-2022.
# Yosef Or Boczko <yoseforb@gmail.com>, 2013-2023.
#
msgid ""
msgstr ""
"Project-Id-Version: gtk+.HEAD.he\n"
"Report-Msgid-Bugs-To: https://gitlab.gnome.org/GNOME/gtk/-/issues/\n"
"POT-Creation-Date: 2022-12-17 12:46+0000\n"
"PO-Revision-Date: 2022-12-27 23:44+0200\n"
"POT-Creation-Date: 2023-01-08 14:30+0000\n"
"PO-Revision-Date: 2023-01-25 10:14+0200\n"
"Last-Translator: Yosef Or Boczko <yoseforb@gmail.com>\n"
"Language-Team: Hebrew <>\n"
"Language: he\n"
@@ -57,27 +57,27 @@ msgstr "לא ניתן לספק תוכן בתור %s"
msgid "The current backend does not support OpenGL"
msgstr "הממשק הנוכחי אינו תומך ב־OpenGL"
#: gdk/gdkdisplay.c:1240
#: gdk/gdkdisplay.c:1242
msgid "GL support disabled via GDK_DEBUG"
msgstr "GL support disabled via GDK_DEBUG"
#: gdk/gdkdisplay.c:1538
#: gdk/gdkdisplay.c:1540
msgid "No EGL configuration available"
msgstr "אין תצורת EGL זמינה"
#: gdk/gdkdisplay.c:1546
#: gdk/gdkdisplay.c:1548
msgid "Failed to get EGL configurations"
msgstr "קבלת תצורות EGL נכשלה"
#: gdk/gdkdisplay.c:1576
#: gdk/gdkdisplay.c:1578
msgid "No EGL configuration with required features found"
msgstr "לא נמצאה תצורת EGL עם היכולות הנדרשות"
#: gdk/gdkdisplay.c:1583
#: gdk/gdkdisplay.c:1585
msgid "No perfect EGL configuration found"
msgstr "לא נמצאה תצורת EGL מושלמת"
#: gdk/gdkdisplay.c:1625
#: gdk/gdkdisplay.c:1627
#, fuzzy, c-format
#| msgid "No GL implementation is available"
msgid "EGL implementation is missing extension %s"
@@ -87,23 +87,23 @@ msgstr[1] "No GL implementation is available"
msgstr[2] "No GL implementation is available"
msgstr[3] "No GL implementation is available"
#: gdk/gdkdisplay.c:1658
#: gdk/gdkdisplay.c:1660
msgid "libEGL not available in this sandbox"
msgstr "libEGL אינו זמין בארגז חול זה"
#: gdk/gdkdisplay.c:1659
#: gdk/gdkdisplay.c:1661
msgid "libEGL not available"
msgstr "libEGL לא זמין"
#: gdk/gdkdisplay.c:1669
#: gdk/gdkdisplay.c:1671
msgid "Failed to create EGL display"
msgstr "יצירת תצוגת EGL נכשלה"
#: gdk/gdkdisplay.c:1679
#: gdk/gdkdisplay.c:1681
msgid "Could not initialize EGL display"
msgstr "לא ניתן להפעיל תצוגת EGL"
#: gdk/gdkdisplay.c:1690
#: gdk/gdkdisplay.c:1692
#, c-format
msgid "EGL version %d.%d is too old. GTK requires %d.%d"
msgstr "גרסת ה־EGL %d.%d ישנה מדי. GTK דורש %d.%d"
@@ -227,12 +227,12 @@ msgctxt "keyboard label"
msgid "Down"
msgstr "מטה"
#: gdk/keynamesprivate.h:6856 gtk/gtkshortcutlabel.c:213
#: gdk/keynamesprivate.h:6856 gtk/gtkshortcutlabel.c:217
msgctxt "keyboard label"
msgid "Page_Up"
msgstr "Page_Up"
#: gdk/keynamesprivate.h:6857 gtk/gtkshortcutlabel.c:216
#: gdk/keynamesprivate.h:6857 gtk/gtkshortcutlabel.c:220
msgctxt "keyboard label"
msgid "Page_Down"
msgstr "Page_Down"
@@ -747,17 +747,17 @@ msgstr "GlobalLock() failed: "
msgid "GlobalAlloc() failed: "
msgstr "GlobalAlloc() failed: "
#: gdk/x11/gdkapplaunchcontext-x11.c:296
#: gdk/x11/gdkapplaunchcontext-x11.c:299
#, c-format
msgid "Starting “%s”"
msgstr "Starting “%s”"
#: gdk/x11/gdkapplaunchcontext-x11.c:309
#: gdk/x11/gdkapplaunchcontext-x11.c:312
#, c-format
msgid "Opening “%s”"
msgstr "Opening “%s”"
#: gdk/x11/gdkapplaunchcontext-x11.c:314
#: gdk/x11/gdkapplaunchcontext-x11.c:317
#, c-format
msgid "Opening %d Item"
msgid_plural "Opening %d Items"
@@ -1052,7 +1052,7 @@ msgid "Sans 12"
msgstr "Sans 12"
#: gtk/deprecated/gtkfontbutton.c:507 gtk/deprecated/gtkfontbutton.c:621
#: gtk/gtkfontdialog.c:595
#: gtk/gtkfontdialog.c:596
msgid "Pick a Font"
msgstr "בחירת גופן"
@@ -1293,7 +1293,7 @@ msgstr "Hyper"
#. * this.
#.
#: gtk/gtkaccelgroup.c:922 gtk/gtkshortcutlabel.c:110
#: gtk/gtkshortcutlabel.c:147
#: gtk/gtkshortcutlabel.c:148
msgctxt "keyboard label"
msgid "Meta"
msgstr "מטה"
@@ -1312,7 +1312,7 @@ msgctxt "keyboard label"
msgid "Space"
msgstr "רווח"
#: gtk/gtkaccelgroup.c:952 gtk/gtkshortcutlabel.c:172
#: gtk/gtkaccelgroup.c:952 gtk/gtkshortcutlabel.c:176
msgctxt "keyboard label"
msgid "Backslash"
msgstr "לוכסן אחורי"
@@ -1709,7 +1709,7 @@ msgctxt "accessibility"
msgid "window"
msgstr "חלון"
#: gtk/gtkalertdialog.c:660 gtk/gtkcustompaperunixdialog.c:328
#: gtk/gtkalertdialog.c:668 gtk/gtkcustompaperunixdialog.c:328
#: gtk/gtkmessagedialog.c:166 gtk/ui/gtkassistant.ui:40
msgid "_Close"
msgstr "_סגירה"
@@ -1804,7 +1804,7 @@ msgstr "%d"
#. * Note that translating this doesn't guarantee that you get localized
#. * digits. That needs support from your system and locale definition
#. * too.
#: gtk/gtkcalendar.c:1495
#: gtk/gtkcalendar.c:1496
#, c-format
msgctxt "calendar:week:digits"
msgid "%d"
@@ -2183,24 +2183,24 @@ msgid "A file with that name already exists"
msgstr "קובץ בשם זה כבר קיים"
#: gtk/gtkfilechoosernative.c:520 gtk/gtkfilechoosernative.c:600
#: gtk/gtkfilechooserwidget.c:1168 gtk/gtkfilechooserwidget.c:4997
#: gtk/gtkfiledialog.c:718 gtk/gtkmessagedialog.c:170
#: gtk/gtkfilechooserwidget.c:1168 gtk/gtkfilechooserwidget.c:5011
#: gtk/gtkfiledialog.c:841 gtk/gtkmessagedialog.c:170
#: gtk/gtkmessagedialog.c:179 gtk/gtkmountoperation.c:608
#: gtk/gtkpagesetupunixdialog.c:283 gtk/gtkprintbackend.c:638
#: gtk/gtkprintunixdialog.c:657 gtk/gtkprintunixdialog.c:814
#: gtk/gtkwindow.c:6156 gtk/ui/gtkappchooserdialog.ui:45
#: gtk/gtkwindow.c:6165 gtk/ui/gtkappchooserdialog.ui:45
#: gtk/ui/gtkassistant.ui:52 gtk/ui/gtkcolorchooserdialog.ui:33
#: gtk/ui/gtkfontchooserdialog.ui:24
msgid "_Cancel"
msgstr "_ביטול"
#: gtk/gtkfilechoosernative.c:521 gtk/gtkfilechoosernative.c:594
#: gtk/gtkfiledialog.c:690 gtk/gtkplacessidebar.c:3145
#: gtk/gtkfiledialog.c:813 gtk/gtkplacessidebar.c:3145
#: gtk/gtkplacessidebar.c:3230 gtk/gtkplacesview.c:1645
msgid "_Open"
msgstr "_פתיחה"
#: gtk/gtkfilechoosernative.c:594 gtk/gtkfiledialog.c:695
#: gtk/gtkfilechoosernative.c:594 gtk/gtkfiledialog.c:818
msgid "_Save"
msgstr "_שמירה"
@@ -2289,12 +2289,13 @@ msgid "Could not select file"
msgstr "לא ניתן לבחור את הקובץ"
#: gtk/gtkfilechooserwidget.c:1702 gtk/ui/gtkfilechooserwidget.ui:66
msgid "Switch to grid view"
msgstr "החלפה לתצוגת רשת"
msgid "Grid View"
msgstr "תצוגת רשת"
#: gtk/gtkfilechooserwidget.c:1708
msgid "Switch to list view"
msgstr "החלפה לתצוגת רשימה"
# msgctxt "accessibility"
msgid "List View"
msgstr "תצוגת רשימה"
#: gtk/gtkfilechooserwidget.c:1773
msgid "_Visit File"
@@ -2374,7 +2375,7 @@ msgstr "בחיפוש"
msgid "Enter location or URL"
msgstr "הזנת מיקום או כתובת"
#: gtk/gtkfilechooserwidget.c:3459 gtk/gtkfilechooserwidget.c:5782
#: gtk/gtkfilechooserwidget.c:3459 gtk/gtkfilechooserwidget.c:5796
#: gtk/ui/gtkfilechooserwidget.ui:383
msgid "Modified"
msgstr "שונה"
@@ -2457,57 +2458,57 @@ msgstr "_כיווניות:מצגת"
msgid "Spreadsheet"
msgstr "גליון נתונים"
#: gtk/gtkfilechooserwidget.c:4989 gtk/gtkprintunixdialog.c:648
#: gtk/gtkfilechooserwidget.c:5003 gtk/gtkprintunixdialog.c:648
#, c-format
msgid "A file named “%s” already exists. Do you want to replace it?"
msgstr "כבר קיים קובץ בשם „%s“. האם להחליפו?"
#: gtk/gtkfilechooserwidget.c:4991 gtk/gtkprintunixdialog.c:652
#: gtk/gtkfilechooserwidget.c:5005 gtk/gtkprintunixdialog.c:652
#, c-format
msgid ""
"The file already exists in “%s”. Replacing it will overwrite its contents."
msgstr "הקובץ כבר קיים תחת „%s“. החלפתו תגרום לאיבוד תוכנו."
#: gtk/gtkfilechooserwidget.c:4997 gtk/gtkprintunixdialog.c:660
#: gtk/gtkfilechooserwidget.c:5011 gtk/gtkprintunixdialog.c:660
msgid "_Replace"
msgstr "ה_חלפה"
#: gtk/gtkfilechooserwidget.c:5152
#: gtk/gtkfilechooserwidget.c:5166
msgid "You do not have access to the specified folder."
msgstr "אין לך גישה לתיקייה המסוימת."
#: gtk/gtkfilechooserwidget.c:5729
#: gtk/gtkfilechooserwidget.c:5743
msgid "Could not send the search request"
msgstr "לא ניתן לשלוח את בקשת החיפוש"
#: gtk/gtkfilechooserwidget.c:6005
#: gtk/gtkfilechooserwidget.c:6019
msgid "Accessed"
msgstr "נצפה לאחרונה"
# hebrew note: "תיקייה" is "folder", but there is no better word for
# "directory"
#: gtk/gtkfiledialog.c:691
#: gtk/gtkfiledialog.c:814
msgid "Pick Files"
msgstr "בחירת קבצים"
#: gtk/gtkfiledialog.c:691
#: gtk/gtkfiledialog.c:814
msgid "Pick a File"
msgstr "בחירת קובץ"
#: gtk/gtkfiledialog.c:696
#: gtk/gtkfiledialog.c:819
msgid "Save a File"
msgstr "שמירץ קובץ"
#: gtk/gtkfiledialog.c:700 gtk/ui/gtkappchooserdialog.ui:50
#: gtk/gtkfiledialog.c:823 gtk/ui/gtkappchooserdialog.ui:50
#: gtk/ui/gtkcolorchooserdialog.ui:38 gtk/ui/gtkfontchooserdialog.ui:29
msgid "_Select"
msgstr "ב_חירה"
#: gtk/gtkfiledialog.c:701
#: gtk/gtkfiledialog.c:824
msgid "Select Folders"
msgstr "בחירת תיקיות"
#: gtk/gtkfiledialog.c:701
#: gtk/gtkfiledialog.c:824
msgid "Select a Folder"
msgstr "בחירת תיקייה"
@@ -2570,8 +2571,12 @@ msgstr "מספר מונה"
msgid "Number Spacing"
msgstr "מספר רווח"
#: gtk/gtkfontchooserwidget.c:2513
# msgctxt "OpenType layout"
msgid "Fractions"
msgstr "שברים"
#: gtk/gtkfontchooserwidget.c:2514
#, fuzzy
msgid "Style Variations"
msgstr "מאפייני סגנון"
@@ -2649,15 +2654,6 @@ msgstr ""
"מדיניות המערכת מונעת ביצוע שינויים.\n"
"‫נא ליצור קשר עם מנהל המערכת"
#. Translate to default:RTL if you want your widgets
#. * to be RTL, otherwise translate to default:LTR.
#. * Do *not* translate it to "predefinito:LTR", if it
#. * it isn't default:LTR or default:RTL it will not work
#.
#: gtk/gtkmain.c:789
msgid "default:LTR"
msgstr "default:RTL"
#. hour:minutes:seconds
#. Translators: This is a time format, like "9:05:02" for 9
#. * hours, 5 minutes, and 2 seconds. You may change ":" to
@@ -2707,7 +2703,7 @@ msgid "%d:%02d"
msgstr "%d:%02d"
#: gtk/gtkmessagedialog.c:162 gtk/gtkmessagedialog.c:180
#: gtk/gtkprintbackend.c:639 gtk/gtkwindow.c:6157
#: gtk/gtkprintbackend.c:639 gtk/gtkwindow.c:6166
msgid "_OK"
msgstr "_אישור"
@@ -3233,11 +3229,11 @@ msgstr "אימות"
msgid "_Remember password"
msgstr "_שמירת הססמה"
#: gtk/gtkprinteroptionwidget.c:739
#: gtk/gtkprinteroptionwidget.c:715
msgid "Select a filename"
msgstr "נא לבחור בקובץ"
#: gtk/gtkprinteroptionwidget.c:947
#: gtk/gtkprinteroptionwidget.c:932
msgid "Not available"
msgstr "לא זמין"
@@ -3615,12 +3611,12 @@ msgctxt "volume percentage"
msgid "%d%%"
msgstr "%d%%"
#: gtk/gtkwindow.c:6145
#: gtk/gtkwindow.c:6154
#, c-format
msgid "Do you want to use GTK Inspector?"
msgstr "להשתמש במפקח GTK?"
#: gtk/gtkwindow.c:6147
#: gtk/gtkwindow.c:6156
#, c-format
msgid ""
"GTK Inspector is an interactive debugger that lets you explore and modify "
@@ -3630,7 +3626,7 @@ msgstr ""
"מפקח GTK הוא מנפה שגיאות הידודי המאפשר לך לחקור ולשנות את הפנים של כל יישום "
"GTK+. שימוש בו יכול לגרום ליישום להישבר או לקרוס."
#: gtk/gtkwindow.c:6152
#: gtk/gtkwindow.c:6161
msgid "Dont show this message again"
msgstr "לא להציג הודעה זו שוב"
@@ -3801,47 +3797,47 @@ msgstr "מחלקות סגנון"
msgid "CSS Property"
msgstr "מאפיין CSS"
#: gtk/inspector/general.c:330 gtk/inspector/general.c:411
#: gtk/inspector/general.c:332 gtk/inspector/general.c:413
msgctxt "GL version"
msgid "None"
msgstr "ללא"
#: gtk/inspector/general.c:339
#: gtk/inspector/general.c:341
msgctxt "GL version"
msgid "Disabled"
msgstr "מושבת"
#: gtk/inspector/general.c:340
#: gtk/inspector/general.c:342
msgctxt "GL vendor"
msgid "Disabled"
msgstr "מושבת"
#: gtk/inspector/general.c:412
#: gtk/inspector/general.c:414
msgctxt "GL vendor"
msgid "None"
msgstr "ללא"
#: gtk/inspector/general.c:463
#: gtk/inspector/general.c:465
msgctxt "Vulkan device"
msgid "Disabled"
msgstr "מושבת"
#: gtk/inspector/general.c:464 gtk/inspector/general.c:465
#: gtk/inspector/general.c:466 gtk/inspector/general.c:467
msgctxt "Vulkan version"
msgid "Disabled"
msgstr "מושבת"
#: gtk/inspector/general.c:521
#: gtk/inspector/general.c:523
msgctxt "Vulkan device"
msgid "None"
msgstr "ללא"
#: gtk/inspector/general.c:522 gtk/inspector/general.c:523
#: gtk/inspector/general.c:524 gtk/inspector/general.c:525
msgctxt "Vulkan version"
msgid "None"
msgstr "ללא"
#: gtk/inspector/general.c:793
#: gtk/inspector/general.c:795
msgid "IM Context is hardcoded by GTK_IM_MODULE"
msgstr "IM Context קשיחה בקוד על ידי GTK_IM_MODULE"
@@ -4414,7 +4410,7 @@ msgid "Child object"
msgstr "עצם צאצא"
#: gtk/inspector/window.ui:341
msgctxt "Stock label, media"
# msgctxt "Stock label, media"
msgid "Previous sibling"
msgstr "אח קודם"
@@ -4653,7 +4649,6 @@ msgctxt "OpenType layout"
msgid "Flattened accent forms"
msgstr ""
#: gtk/gtkfontchooserwidget.c:2513
#: gtk/open-type-layout.h:45
msgctxt "OpenType layout"
msgid "Fractions"
@@ -7266,13 +7261,13 @@ msgstr "Show program version"
#. Translators: this message will appear immediately after the
#. usage string - Usage: COMMAND [OPTION…] <THIS_MESSAGE>
#: tools/gtk-launch.c:72
#: tools/gtk-launch.c:74
msgid "APPLICATION [URI…] — launch an APPLICATION"
msgstr "APPLICATION [URI…] — launch an APPLICATION"
#. Translators: this message will appear after the usage string
#. and before the list of options.
#: tools/gtk-launch.c:76
#: tools/gtk-launch.c:78
msgid ""
"Launch an application (specified by its desktop file name),\n"
"optionally passing one or more URIs as arguments."
@@ -7280,38 +7275,38 @@ msgstr ""
"Launch an application (specified by its desktop file name),\n"
"optionally passing one or more URIs as arguments."
#: tools/gtk-launch.c:86
#: tools/gtk-launch.c:88
#, c-format
msgid "Error parsing commandline options: %s\n"
msgstr "Error parsing commandline options: %s\n"
#: tools/gtk-launch.c:88 tools/gtk-launch.c:109
#: tools/gtk-launch.c:90 tools/gtk-launch.c:111
#, c-format
msgid "Try “%s --help” for more information."
msgstr "כדאי לנסות את „‎%s --help” למידע נוסף."
#. Translators: the %s is the program name. This error message
#. means the user is calling gtk-launch without any argument.
#: tools/gtk-launch.c:107
#: tools/gtk-launch.c:109
#, c-format
msgid "%s: missing application name"
msgstr "%s: missing application name"
#: tools/gtk-launch.c:136
#: tools/gtk-launch.c:137
#, c-format
msgid "Creating AppInfo from id not supported on non unix operating systems"
msgstr "Creating AppInfo from id not supported on non unix operating systems"
#. Translators: the first %s is the program name, the second one
#. is the application name.
#: tools/gtk-launch.c:144
#: tools/gtk-launch.c:145
#, c-format
msgid "%s: no such application %s"
msgstr "%s: no such application %s"
#. Translators: the first %s is the program name, the second one
#. is the error message.
#: tools/gtk-launch.c:162
#: tools/gtk-launch.c:163
#, c-format
msgid "%s: error launching application: %s\n"
msgstr "%s: error launching application: %s\n"
@@ -7423,6 +7418,15 @@ msgstr ""
"No theme index file in “%s”.\n"
"If you really want to create an icon cache here, use --ignore-theme-index.\n"
#~ msgid "Switch to grid view"
#~ msgstr "החלפה לתצוגת רשת"
#~ msgid "Switch to list view"
#~ msgstr "החלפה לתצוגת רשימה"
#~ msgid "default:LTR"
#~ msgstr "default:RTL"
#~ msgid "Other application…"
#~ msgstr "יישום אחר…"

1605
po/pt.po

File diff suppressed because it is too large Load Diff

224
po/uk.po
View File

@@ -4,13 +4,13 @@
# Maxim Dziumanenko <dziumanenko@gmail.com>, 2004-2010.
# wanderlust <wanderlust@ukr.net>, 2009.
# Daniel Korostil <ted.korostiled@gmail.com>, 2013, 2014, 2015, 2016.
# Yuri Chornoivan <yurchor@ukr.net>, 2014, 2020, 2021, 2022.
# Yuri Chornoivan <yurchor@ukr.net>, 2014, 2020, 2021, 2022, 2023.
msgid ""
msgstr ""
"Project-Id-Version: gtk+\n"
"Report-Msgid-Bugs-To: https://gitlab.gnome.org/GNOME/gtk/-/issues/\n"
"POT-Creation-Date: 2022-12-17 12:46+0000\n"
"PO-Revision-Date: 2022-12-23 15:48+0200\n"
"POT-Creation-Date: 2023-01-25 20:24+0000\n"
"PO-Revision-Date: 2023-01-27 21:22+0200\n"
"Last-Translator: Yuri Chornoivan <yurchor@ukr.net>\n"
"Language-Team: Ukrainian <trans-uk@lists.fedoraproject.org>\n"
"Language: uk\n"
@@ -54,27 +54,27 @@ msgstr "Не вдалося надати дані як %s"
msgid "The current backend does not support OpenGL"
msgstr "Цей модуль не підтримує OpenGL"
#: gdk/gdkdisplay.c:1240
#: gdk/gdkdisplay.c:1242
msgid "GL support disabled via GDK_DEBUG"
msgstr "Вимкнено підтримування GL через GDK_DEBUG"
#: gdk/gdkdisplay.c:1538
#: gdk/gdkdisplay.c:1540
msgid "No EGL configuration available"
msgstr "Немає доступних налаштувань EGL"
#: gdk/gdkdisplay.c:1546
#: gdk/gdkdisplay.c:1548
msgid "Failed to get EGL configurations"
msgstr "Не вдалося отримати налаштування EGL"
#: gdk/gdkdisplay.c:1576
#: gdk/gdkdisplay.c:1578
msgid "No EGL configuration with required features found"
msgstr "Не знайдено налаштувань EGL із потрібними можливостями"
#: gdk/gdkdisplay.c:1583
#: gdk/gdkdisplay.c:1585
msgid "No perfect EGL configuration found"
msgstr "Не знайдено ідеальних налаштувань EGL"
#: gdk/gdkdisplay.c:1625
#: gdk/gdkdisplay.c:1627
#, c-format
msgid "EGL implementation is missing extension %s"
msgid_plural "EGL implementation is missing %2$d extensions: %1$s"
@@ -83,23 +83,23 @@ msgstr[1] "У реалізації EGL не вистачає %2$d розшире
msgstr[2] "У реалізації EGL не вистачає %2$d розширень %1$s"
msgstr[3] "У реалізації EGL не вистачає розширення %1$s"
#: gdk/gdkdisplay.c:1658
#: gdk/gdkdisplay.c:1660
msgid "libEGL not available in this sandbox"
msgstr "libEGL є недоступною у цій пісочниці"
#: gdk/gdkdisplay.c:1659
#: gdk/gdkdisplay.c:1661
msgid "libEGL not available"
msgstr "libEGL є недоступною"
#: gdk/gdkdisplay.c:1669
#: gdk/gdkdisplay.c:1671
msgid "Failed to create EGL display"
msgstr "Не вдалося створити запис дисплея EGL"
#: gdk/gdkdisplay.c:1679
#: gdk/gdkdisplay.c:1681
msgid "Could not initialize EGL display"
msgstr "Не вдалося ініціалізувати дисплей EGL"
#: gdk/gdkdisplay.c:1690
#: gdk/gdkdisplay.c:1692
#, c-format
msgid "EGL version %d.%d is too old. GTK requires %d.%d"
msgstr ""
@@ -223,12 +223,12 @@ msgctxt "keyboard label"
msgid "Down"
msgstr "Вниз"
#: gdk/keynamesprivate.h:6856 gtk/gtkshortcutlabel.c:213
#: gdk/keynamesprivate.h:6856 gtk/gtkshortcutlabel.c:217
msgctxt "keyboard label"
msgid "Page_Up"
msgstr "Page_Up"
#: gdk/keynamesprivate.h:6857 gtk/gtkshortcutlabel.c:216
#: gdk/keynamesprivate.h:6857 gtk/gtkshortcutlabel.c:220
msgctxt "keyboard label"
msgid "Page_Down"
msgstr "Page_Down"
@@ -567,18 +567,13 @@ msgstr "Не вдалося завантажити дані TIFF"
msgid "Reading data failed at row %d"
msgstr "Помилка читання даних у рядку %d"
#: gdk/macos/gdkmacosclipboard.c:557 gdk/wayland/gdkclipboard-wayland.c:240
#: gdk/wayland/gdkdrop-wayland.c:208 gdk/wayland/gdkprimary-wayland.c:336
#: gdk/win32/gdkdrop-win32.c:1018 gdk/win32/gdkdrop-win32.c:1063
#: gdk/x11/gdkclipboard-x11.c:805 gdk/x11/gdkdrop-x11.c:235
#: gdk/wayland/gdkclipboard-wayland.c:240 gdk/wayland/gdkdrop-wayland.c:208
#: gdk/wayland/gdkprimary-wayland.c:336 gdk/win32/gdkdrop-win32.c:1018
#: gdk/win32/gdkdrop-win32.c:1063 gdk/x11/gdkclipboard-x11.c:805
#: gdk/x11/gdkdrop-x11.c:235
msgid "No compatible transfer format found"
msgstr "Не знайдено сумісного формату передавання даних"
#: gdk/macos/gdkmacosclipboard.c:643
#, c-format
msgid "Failed to decode contents with mime-type of '%s'"
msgstr "Не вдалося декодувати дані з типом MIME «%s»"
#: gdk/win32/gdkclipdrop-win32.c:721
#, c-format
msgid "Cannot claim clipboard ownership. OpenClipboard() timed out."
@@ -774,17 +769,17 @@ msgstr "Помилка GlobalLock(): "
msgid "GlobalAlloc() failed: "
msgstr "Помилка GlobalAlloc(): "
#: gdk/x11/gdkapplaunchcontext-x11.c:296
#: gdk/x11/gdkapplaunchcontext-x11.c:299
#, c-format
msgid "Starting “%s”"
msgstr "Запускання «%s»"
#: gdk/x11/gdkapplaunchcontext-x11.c:309
#: gdk/x11/gdkapplaunchcontext-x11.c:312
#, c-format
msgid "Opening “%s”"
msgstr "Відкриваємо «%s»"
#: gdk/x11/gdkapplaunchcontext-x11.c:314
#: gdk/x11/gdkapplaunchcontext-x11.c:317
#, c-format
msgid "Opening %d Item"
msgid_plural "Opening %d Items"
@@ -973,7 +968,6 @@ msgid "Could not unescape string"
msgstr "Не вдалося вилучити екранування символів у рядку"
#: gtk/deprecated/gtkappchooserbutton.c:323
#| msgid "Other…"
msgid "Other app…"
msgstr "Інша програма…"
@@ -1009,28 +1003,23 @@ msgid "Failed to start GNOME Software"
msgstr "Не вдалося запустити «Програмні засоби GNOME»"
#: gtk/deprecated/gtkappchooserwidget.c:525
#| msgid "Default"
msgid "Default App"
msgstr "Типова програма"
#: gtk/deprecated/gtkappchooserwidget.c:575
#, c-format
#| msgid "No applications found for “%s”."
msgid "No apps found for “%s”."
msgstr "Не знайдено програм для «%s»."
#: gtk/deprecated/gtkappchooserwidget.c:658
#| msgid "Recommended Applications"
msgid "Recommended Apps"
msgstr "Рекомендовані програми"
#: gtk/deprecated/gtkappchooserwidget.c:673
#| msgid "Related Applications"
msgid "Related Apps"
msgstr "Пов'язані програми"
#: gtk/deprecated/gtkappchooserwidget.c:687
#| msgid "Other Applications"
msgid "Other Apps"
msgstr "Інші програми"
@@ -1089,7 +1078,7 @@ msgid "Sans 12"
msgstr "Sans 12"
#: gtk/deprecated/gtkfontbutton.c:507 gtk/deprecated/gtkfontbutton.c:621
#: gtk/gtkfontdialog.c:595
#: gtk/gtkfontdialog.c:596
msgid "Pick a Font"
msgstr "Виберіть шрифт"
@@ -1103,7 +1092,7 @@ msgctxt "font"
msgid "None"
msgstr "Немає"
#: gtk/deprecated/gtkshow.c:176
#: gtk/deprecated/gtkshow.c:178
msgid "Could not show link"
msgstr "Не вдалось показати посилання"
@@ -1181,35 +1170,35 @@ msgstr "Ліцензія Apache, версія 2.0"
msgid "Mozilla Public License 2.0"
msgstr "Громадська ліцензія Mozilla 2.0"
#: gtk/gtkaboutdialog.c:970
#: gtk/gtkaboutdialog.c:967
msgid "Website"
msgstr "Сайт"
#: gtk/gtkaboutdialog.c:1006 gtk/ui/gtkapplication-quartz.ui:6
#: gtk/gtkaboutdialog.c:1003 gtk/ui/gtkapplication-quartz.ui:6
#, c-format
msgid "About %s"
msgstr "Про %s"
#: gtk/gtkaboutdialog.c:2096
#: gtk/gtkaboutdialog.c:2093
msgid "Created by"
msgstr "Створення"
#: gtk/gtkaboutdialog.c:2099
#: gtk/gtkaboutdialog.c:2096
msgid "Documented by"
msgstr "Документація"
#: gtk/gtkaboutdialog.c:2109
#: gtk/gtkaboutdialog.c:2106
msgid "Translated by"
msgstr "Переклад"
#: gtk/gtkaboutdialog.c:2114
#: gtk/gtkaboutdialog.c:2111
msgid "Design by"
msgstr "Дизайн"
#. Translators: this is the license preamble; the string at the end
#. * contains the name of the license as link text.
#.
#: gtk/gtkaboutdialog.c:2279
#: gtk/gtkaboutdialog.c:2276
#, c-format
msgid ""
"This program comes with absolutely no warranty.\n"
@@ -1279,7 +1268,7 @@ msgstr "Hyper"
#. * this.
#.
#: gtk/gtkaccelgroup.c:922 gtk/gtkshortcutlabel.c:110
#: gtk/gtkshortcutlabel.c:147
#: gtk/gtkshortcutlabel.c:148
msgctxt "keyboard label"
msgid "Meta"
msgstr "Meta"
@@ -1298,7 +1287,7 @@ msgctxt "keyboard label"
msgid "Space"
msgstr "Пробіл"
#: gtk/gtkaccelgroup.c:952 gtk/gtkshortcutlabel.c:172
#: gtk/gtkaccelgroup.c:952 gtk/gtkshortcutlabel.c:176
msgctxt "keyboard label"
msgid "Backslash"
msgstr "Backslash"
@@ -1693,7 +1682,7 @@ msgctxt "accessibility"
msgid "window"
msgstr "вікно"
#: gtk/gtkalertdialog.c:660 gtk/gtkcustompaperunixdialog.c:328
#: gtk/gtkalertdialog.c:668 gtk/gtkcustompaperunixdialog.c:328
#: gtk/gtkmessagedialog.c:166 gtk/ui/gtkassistant.ui:40
msgid "_Close"
msgstr "_Закрити"
@@ -1788,7 +1777,7 @@ msgstr "%d"
#. * Note that translating this doesn't guarantee that you get localized
#. * digits. That needs support from your system and locale definition
#. * too.
#: gtk/gtkcalendar.c:1495
#: gtk/gtkcalendar.c:1496
#, c-format
msgctxt "calendar:week:digits"
msgid "%d"
@@ -2167,24 +2156,24 @@ msgid "A file with that name already exists"
msgstr "Файл з такою назвою вже існує"
#: gtk/gtkfilechoosernative.c:520 gtk/gtkfilechoosernative.c:600
#: gtk/gtkfilechooserwidget.c:1168 gtk/gtkfilechooserwidget.c:4997
#: gtk/gtkfiledialog.c:718 gtk/gtkmessagedialog.c:170
#: gtk/gtkfilechooserwidget.c:1168 gtk/gtkfilechooserwidget.c:5011
#: gtk/gtkfiledialog.c:841 gtk/gtkmessagedialog.c:170
#: gtk/gtkmessagedialog.c:179 gtk/gtkmountoperation.c:608
#: gtk/gtkpagesetupunixdialog.c:283 gtk/gtkprintbackend.c:638
#: gtk/gtkprintunixdialog.c:657 gtk/gtkprintunixdialog.c:814
#: gtk/gtkwindow.c:6156 gtk/ui/gtkappchooserdialog.ui:45
#: gtk/gtkwindow.c:6155 gtk/ui/gtkappchooserdialog.ui:45
#: gtk/ui/gtkassistant.ui:52 gtk/ui/gtkcolorchooserdialog.ui:33
#: gtk/ui/gtkfontchooserdialog.ui:24
msgid "_Cancel"
msgstr "_Скасувати"
#: gtk/gtkfilechoosernative.c:521 gtk/gtkfilechoosernative.c:594
#: gtk/gtkfiledialog.c:690 gtk/gtkplacessidebar.c:3145
#: gtk/gtkfiledialog.c:813 gtk/gtkplacessidebar.c:3145
#: gtk/gtkplacessidebar.c:3230 gtk/gtkplacesview.c:1645
msgid "_Open"
msgstr "_Відкрити"
#: gtk/gtkfilechoosernative.c:594 gtk/gtkfiledialog.c:695
#: gtk/gtkfilechoosernative.c:594 gtk/gtkfiledialog.c:818
msgid "_Save"
msgstr "З_берегти"
@@ -2260,7 +2249,7 @@ msgid "If you delete an item, it will be permanently lost."
msgstr "Якщо вилучити об'єкт, його буде втрачено назавжди."
#: gtk/gtkfilechooserwidget.c:1168 gtk/gtkfilechooserwidget.c:1793
#: gtk/gtklabel.c:5661 gtk/gtktext.c:6087 gtk/gtktextview.c:8997
#: gtk/gtklabel.c:5658 gtk/gtktext.c:6087 gtk/gtktextview.c:8997
msgid "_Delete"
msgstr "В_илучити"
@@ -2273,12 +2262,14 @@ msgid "Could not select file"
msgstr "Не вдалось вибрати файл"
#: gtk/gtkfilechooserwidget.c:1702 gtk/ui/gtkfilechooserwidget.ui:66
msgid "Switch to grid view"
msgstr "Перемкнутися на перегляд таблиці"
msgid "Grid View"
msgstr "Перегляд ґраткою"
#: gtk/gtkfilechooserwidget.c:1708
msgid "Switch to list view"
msgstr "Перемкнутися на перегляд списку"
#| msgctxt "accessibility"
#| msgid "list item"
msgid "List View"
msgstr "Перегляд списком"
#: gtk/gtkfilechooserwidget.c:1773
msgid "_Visit File"
@@ -2358,7 +2349,7 @@ msgstr "Пошук"
msgid "Enter location or URL"
msgstr "Увести адресу або URL"
#: gtk/gtkfilechooserwidget.c:3459 gtk/gtkfilechooserwidget.c:5782
#: gtk/gtkfilechooserwidget.c:3459 gtk/gtkfilechooserwidget.c:5796
#: gtk/ui/gtkfilechooserwidget.ui:383
msgid "Modified"
msgstr "Змінено"
@@ -2441,60 +2432,55 @@ msgstr "Презентація"
msgid "Spreadsheet"
msgstr "Електронна таблиця"
#: gtk/gtkfilechooserwidget.c:4989 gtk/gtkprintunixdialog.c:648
#: gtk/gtkfilechooserwidget.c:5003 gtk/gtkprintunixdialog.c:648
#, c-format
msgid "A file named “%s” already exists. Do you want to replace it?"
msgstr "Файл з назвою «%s» вже існує. Замінити його?"
#: gtk/gtkfilechooserwidget.c:4991 gtk/gtkprintunixdialog.c:652
#: gtk/gtkfilechooserwidget.c:5005 gtk/gtkprintunixdialog.c:652
#, c-format
msgid ""
"The file already exists in “%s”. Replacing it will overwrite its contents."
msgstr "Файл у «%s» вже існує. Перезапис призведе до втрати вмісту."
#: gtk/gtkfilechooserwidget.c:4997 gtk/gtkprintunixdialog.c:660
#: gtk/gtkfilechooserwidget.c:5011 gtk/gtkprintunixdialog.c:660
msgid "_Replace"
msgstr "_Замінити"
#: gtk/gtkfilechooserwidget.c:5152
#: gtk/gtkfilechooserwidget.c:5166
msgid "You do not have access to the specified folder."
msgstr "Ви не маєте доступу до вказаної теки."
#: gtk/gtkfilechooserwidget.c:5729
#: gtk/gtkfilechooserwidget.c:5743
msgid "Could not send the search request"
msgstr "Не вдалось надіслати запит на пошук"
#: gtk/gtkfilechooserwidget.c:6005
#: gtk/gtkfilechooserwidget.c:6019
msgid "Accessed"
msgstr "Дозволено"
#: gtk/gtkfiledialog.c:691
#| msgid "Print to File"
#: gtk/gtkfiledialog.c:814
msgid "Pick Files"
msgstr "Вибір файлів"
#: gtk/gtkfiledialog.c:691
#| msgid "Pick a Font"
#: gtk/gtkfiledialog.c:814
msgid "Pick a File"
msgstr "Вибір файла"
#: gtk/gtkfiledialog.c:696
#| msgid "Select a File"
#: gtk/gtkfiledialog.c:819
msgid "Save a File"
msgstr "Зберегти файл"
#: gtk/gtkfiledialog.c:700 gtk/ui/gtkappchooserdialog.ui:50
#: gtk/gtkfiledialog.c:823 gtk/ui/gtkappchooserdialog.ui:50
#: gtk/ui/gtkcolorchooserdialog.ui:38 gtk/ui/gtkfontchooserdialog.ui:29
msgid "_Select"
msgstr "_Вибрати"
#: gtk/gtkfiledialog.c:701
#| msgid "Select a File"
#: gtk/gtkfiledialog.c:824
msgid "Select Folders"
msgstr "Вибір тек"
#: gtk/gtkfiledialog.c:701
#| msgid "Select a File"
#: gtk/gtkfiledialog.c:824
msgid "Select a Folder"
msgstr "Вибір теки"
@@ -2573,27 +2559,27 @@ msgstr "Варіанти символів"
msgid "OpenGL context creation failed"
msgstr "Не вдалося створити контекст OpenGL"
#: gtk/gtklabel.c:5658 gtk/gtktext.c:6075 gtk/gtktextview.c:8985
#: gtk/gtklabel.c:5655 gtk/gtktext.c:6075 gtk/gtktextview.c:8985
msgid "Cu_t"
msgstr "Ви_різати"
#: gtk/gtklabel.c:5659 gtk/gtktext.c:6079 gtk/gtktextview.c:8989
#: gtk/gtklabel.c:5656 gtk/gtktext.c:6079 gtk/gtktextview.c:8989
msgid "_Copy"
msgstr "_Копіювати"
#: gtk/gtklabel.c:5660 gtk/gtktext.c:6083 gtk/gtktextview.c:8993
#: gtk/gtklabel.c:5657 gtk/gtktext.c:6083 gtk/gtktextview.c:8993
msgid "_Paste"
msgstr "Вст_авити"
#: gtk/gtklabel.c:5666 gtk/gtktext.c:6096 gtk/gtktextview.c:9018
#: gtk/gtklabel.c:5663 gtk/gtktext.c:6096 gtk/gtktextview.c:9018
msgid "Select _All"
msgstr "Виді_лити все"
#: gtk/gtklabel.c:5671
#: gtk/gtklabel.c:5668
msgid "_Open Link"
msgstr "_Відкрити посилання"
#: gtk/gtklabel.c:5675
#: gtk/gtklabel.c:5672
msgid "Copy _Link Address"
msgstr "Копіювати _адресу посилання"
@@ -2601,7 +2587,7 @@ msgstr "Копіювати _адресу посилання"
msgid "_Copy URL"
msgstr "_Копіювати адресу"
#: gtk/gtklinkbutton.c:547
#: gtk/gtklinkbutton.c:544
msgid "Invalid URI"
msgstr "Неправильний URI"
@@ -2637,15 +2623,6 @@ msgstr ""
"Системна політика забороняє зміни.\n"
"Зв'яжіться з системним адміністратором"
#. Translate to default:RTL if you want your widgets
#. * to be RTL, otherwise translate to default:LTR.
#. * Do *not* translate it to "predefinito:LTR", if it
#. * it isn't default:LTR or default:RTL it will not work
#.
#: gtk/gtkmain.c:789
msgid "default:LTR"
msgstr "default:LTR"
#. hour:minutes:seconds
#. Translators: This is a time format, like "9:05:02" for 9
#. * hours, 5 minutes, and 2 seconds. You may change ":" to
@@ -2695,7 +2672,7 @@ msgid "%d:%02d"
msgstr "%d:%02d"
#: gtk/gtkmessagedialog.c:162 gtk/gtkmessagedialog.c:180
#: gtk/gtkprintbackend.c:639 gtk/gtkwindow.c:6157
#: gtk/gtkprintbackend.c:639 gtk/gtkwindow.c:6156
msgid "_OK"
msgstr "_Гаразд"
@@ -3221,11 +3198,11 @@ msgstr "Автентифікація"
msgid "_Remember password"
msgstr "_Запам'ятати пароль"
#: gtk/gtkprinteroptionwidget.c:739
#: gtk/gtkprinteroptionwidget.c:715
msgid "Select a filename"
msgstr "Вибрати назву файла"
#: gtk/gtkprinteroptionwidget.c:947
#: gtk/gtkprinteroptionwidget.c:932
msgid "Not available"
msgstr "Недоступно"
@@ -3605,12 +3582,12 @@ msgctxt "volume percentage"
msgid "%d%%"
msgstr "%d%%"
#: gtk/gtkwindow.c:6145
#: gtk/gtkwindow.c:6144
#, c-format
msgid "Do you want to use GTK Inspector?"
msgstr "Бажаєте використовувати інспектор GTK?"
#: gtk/gtkwindow.c:6147
#: gtk/gtkwindow.c:6146
#, c-format
msgid ""
"GTK Inspector is an interactive debugger that lets you explore and modify "
@@ -3621,7 +3598,7 @@ msgstr ""
"редагувати внутрішні частини будь-які програми GTK. Його використання може "
"спричинити збої в програмі."
#: gtk/gtkwindow.c:6152
#: gtk/gtkwindow.c:6151
msgid "Dont show this message again"
msgstr "Не показувати це повідомлення надалі"
@@ -3793,47 +3770,47 @@ msgstr "Класи стилів"
msgid "CSS Property"
msgstr "Властивість CSS"
#: gtk/inspector/general.c:330 gtk/inspector/general.c:411
#: gtk/inspector/general.c:332 gtk/inspector/general.c:413
msgctxt "GL version"
msgid "None"
msgstr "Немає"
#: gtk/inspector/general.c:339
#: gtk/inspector/general.c:341
msgctxt "GL version"
msgid "Disabled"
msgstr "Вимкнено"
#: gtk/inspector/general.c:340
#: gtk/inspector/general.c:342
msgctxt "GL vendor"
msgid "Disabled"
msgstr "Вимкнено"
#: gtk/inspector/general.c:412
#: gtk/inspector/general.c:414
msgctxt "GL vendor"
msgid "None"
msgstr "Немає"
#: gtk/inspector/general.c:463
#: gtk/inspector/general.c:465
msgctxt "Vulkan device"
msgid "Disabled"
msgstr "Вимкнено"
#: gtk/inspector/general.c:464 gtk/inspector/general.c:465
#: gtk/inspector/general.c:466 gtk/inspector/general.c:467
msgctxt "Vulkan version"
msgid "Disabled"
msgstr "Вимкнено"
#: gtk/inspector/general.c:521
#: gtk/inspector/general.c:523
msgctxt "Vulkan device"
msgid "None"
msgstr "Немає"
#: gtk/inspector/general.c:522 gtk/inspector/general.c:523
#: gtk/inspector/general.c:524 gtk/inspector/general.c:525
msgctxt "Vulkan version"
msgid "None"
msgstr "Немає"
#: gtk/inspector/general.c:793
#: gtk/inspector/general.c:795
msgid "IM Context is hardcoded by GTK_IM_MODULE"
msgstr "Контекст способу введення жорстко встановлено у GTK_IM_MODULE"
@@ -4240,12 +4217,10 @@ msgstr "Увімкнути статистику з GOBJECT_DEBUG=instance-count"
#: gtk/inspector/strv-editor.c:83
#, c-format
#| msgid "_Remove"
msgid "Remove %s"
msgstr "Вилучити %s"
#: gtk/inspector/strv-editor.c:115
#| msgid "Address"
msgid "Add"
msgstr "Додати"
@@ -6012,17 +5987,14 @@ msgid "System"
msgstr "Система"
#: gtk/ui/gtkappchooserdialog.ui:4
#| msgid "Select _All"
msgid "Select App"
msgstr "Вибір програми"
#: gtk/ui/gtkappchooserdialog.ui:60
#| msgid "_View All Applications"
msgid "_View All Apps"
msgstr "П_ереглянути усі програми"
#: gtk/ui/gtkappchooserdialog.ui:66
#| msgid "_Find New Applications"
msgid "_Find New Apps"
msgstr "_Знайти нові програми"
@@ -7145,7 +7117,6 @@ msgid "FILE"
msgstr "ФАЙЛ"
#: tools/gtk-builder-tool-enumerate.c:64
#| msgid "List all named objects."
msgid "Print all named objects."
msgstr "Вивести список усіх іменованих об'єктів."
@@ -7245,13 +7216,13 @@ msgstr "Показати версію програми"
#. Translators: this message will appear immediately after the
#. usage string - Usage: COMMAND [OPTION…] <THIS_MESSAGE>
#: tools/gtk-launch.c:72
#: tools/gtk-launch.c:74
msgid "APPLICATION [URI…] — launch an APPLICATION"
msgstr "ПРОГРАМА [URI…] — запустити програму."
#. Translators: this message will appear after the usage string
#. and before the list of options.
#: tools/gtk-launch.c:76
#: tools/gtk-launch.c:78
msgid ""
"Launch an application (specified by its desktop file name),\n"
"optionally passing one or more URIs as arguments."
@@ -7259,24 +7230,24 @@ msgstr ""
"Запустити програму (вказану через її стільничну назву файла),\n"
"за бажанням пропускати один або кілька URI як аргументи."
#: tools/gtk-launch.c:86
#: tools/gtk-launch.c:88
#, c-format
msgid "Error parsing commandline options: %s\n"
msgstr "Помилка розбирання параметрів командного рядка: %s\n"
#: tools/gtk-launch.c:88 tools/gtk-launch.c:109
#: tools/gtk-launch.c:90 tools/gtk-launch.c:111
#, c-format
msgid "Try “%s --help” for more information."
msgstr "Скористайтеся «%s --help» для отримання докладної інформації."
#. Translators: the %s is the program name. This error message
#. means the user is calling gtk-launch without any argument.
#: tools/gtk-launch.c:107
#: tools/gtk-launch.c:109
#, c-format
msgid "%s: missing application name"
msgstr "%s: бракує назви програми"
#: tools/gtk-launch.c:136
#: tools/gtk-launch.c:137
#, c-format
msgid "Creating AppInfo from id not supported on non unix operating systems"
msgstr ""
@@ -7285,14 +7256,14 @@ msgstr ""
#. Translators: the first %s is the program name, the second one
#. is the application name.
#: tools/gtk-launch.c:144
#: tools/gtk-launch.c:145
#, c-format
msgid "%s: no such application %s"
msgstr "%s: нема такої програми %s"
#. Translators: the first %s is the program name, the second one
#. is the error message.
#: tools/gtk-launch.c:162
#: tools/gtk-launch.c:163
#, c-format
msgid "%s: error launching application: %s\n"
msgstr "%s: помилка запускання програми: %s\n"
@@ -7405,6 +7376,19 @@ msgstr ""
"Якщо ви дійсно бажаєте створити тут кеш значків, використовуйте --ignore-"
"theme-index.\n"
#, c-format
#~ msgid "Failed to decode contents with mime-type of '%s'"
#~ msgstr "Не вдалося декодувати дані з типом MIME «%s»"
#~ msgid "Switch to grid view"
#~ msgstr "Перемкнутися на перегляд таблиці"
#~ msgid "Switch to list view"
#~ msgstr "Перемкнутися на перегляд списку"
#~ msgid "default:LTR"
#~ msgstr "default:LTR"
#~ msgid "Other application…"
#~ msgstr "Інша програма…"