Compare commits
85 Commits
3.34.2
...
gnome-3-34
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
a416bed34c | ||
|
|
80c0a470e7 | ||
|
|
8802f7f0d8 | ||
|
|
8b3f1117be | ||
|
|
48ffbb5824 | ||
|
|
129d134704 | ||
|
|
4078ba1828 | ||
|
|
fd8ccbac82 | ||
|
|
93417d0ceb | ||
|
|
3bafd23424 | ||
|
|
e328fcc379 | ||
|
|
e845bbd579 | ||
|
|
025730349d | ||
|
|
f6d0af0c93 | ||
|
|
8acff5309d | ||
|
|
0ab8b17433 | ||
|
|
50f383d2e9 | ||
|
|
7fbba4ad14 | ||
|
|
eb6189d6b6 | ||
|
|
668d13ffb5 | ||
|
|
02947e7872 | ||
|
|
ebfe5e44c2 | ||
|
|
8f64b3dcad | ||
|
|
8de5b95123 | ||
|
|
cedab9442f | ||
|
|
7cc5ed96fc | ||
|
|
bb831f04c5 | ||
|
|
c92267feb2 | ||
|
|
8240aba80f | ||
|
|
5f34a0f245 | ||
|
|
83eeb3dbd2 | ||
|
|
c25011ffba | ||
|
|
abd67819fe | ||
|
|
6f3b7b733a | ||
|
|
e2c61f2739 | ||
|
|
1a3dfd8110 | ||
|
|
aeb781acd6 | ||
|
|
092591b872 | ||
|
|
57992f37cc | ||
|
|
7655a63af6 | ||
|
|
a5b5e95ad9 | ||
|
|
11da42b2f8 | ||
|
|
2709a4ffb1 | ||
|
|
c65db40178 | ||
|
|
011ff15603 | ||
|
|
c3d2f3f399 | ||
|
|
053bb5901a | ||
|
|
0bce4323c7 | ||
|
|
b2bc345463 | ||
|
|
2235629d25 | ||
|
|
59da900a45 | ||
|
|
0e0dae2774 | ||
|
|
4959ae8bc4 | ||
|
|
aea5541ffa | ||
|
|
47fe7ac25b | ||
|
|
d35d7fb618 | ||
|
|
666bd25005 | ||
|
|
208fd1b083 | ||
|
|
12152c7edb | ||
|
|
de7782221a | ||
|
|
651d2a57f8 | ||
|
|
e18aa564b0 | ||
|
|
4cc5b85c5d | ||
|
|
ca5ed7369d | ||
|
|
5ae317e004 | ||
|
|
21dca32934 | ||
|
|
41c6e1375b | ||
|
|
d38c30c128 | ||
|
|
59e9b073a5 | ||
|
|
6b6e724425 | ||
|
|
156dd576f4 | ||
|
|
4d0a331cfe | ||
|
|
01d93f2819 | ||
|
|
be777dbd79 | ||
|
|
a9a0110818 | ||
|
|
fd7d0fb339 | ||
|
|
1671692590 | ||
|
|
06fc756f0f | ||
|
|
81b7196ad9 | ||
|
|
e91b12fdf9 | ||
|
|
f52c0a3bf7 | ||
|
|
78a45e1813 | ||
|
|
4947e8ae5b | ||
|
|
5724310899 | ||
|
|
9772f084bf |
53
NEWS
53
NEWS
@@ -1,3 +1,56 @@
|
||||
3.34.6
|
||||
======
|
||||
* Fix various clipboard issues [Carlos; !1198, !1203, !1204, !1186, !1206]
|
||||
* Fix locate-pointer feature interfering with keybindings [Carlos; !1014]
|
||||
* Fix overview key on X11 when using multiple keyboard layouts [Olivier; !1219]
|
||||
* Preserve keyboard state on VT switch [Olivier; !1185]
|
||||
* Fixed crashes [Florian; #1083]
|
||||
* Plugged memory leaks [Sebastian; !1001]
|
||||
* Misc. bug fixes and cleanups [Pekka, Laurent; !1209, #1074]
|
||||
|
||||
Contributors:
|
||||
Laurent Bigonville, Olivier Fourdan, Carlos Garnacho, Sebastian Keller,
|
||||
Florian Müllner, Pekka Paalanen
|
||||
|
||||
3.34.5
|
||||
======
|
||||
* Fix visibility of initially hidden windows [Jonas; !1066]
|
||||
* Fix hardware cursor on GPU hotplug [Pekka; !1097]
|
||||
* Fix pasting images from wayland [Robert, Carlos; !1141, #1065]
|
||||
* Fixed crashes [Florian, Olivier, Jonas; #1029, !1073, !1121, !1120]
|
||||
|
||||
Contributors:
|
||||
Olivier Fourdan, Carlos Garnacho, Robert Mader, Florian Müllner,
|
||||
Pekka Paalanen, Jonas Ådahl
|
||||
|
||||
Translators:
|
||||
Yi-Jyun Pan [zh_TW]
|
||||
3.34.4
|
||||
======
|
||||
* Handle mode set race conditions more gracefully [Jonas; !1007]
|
||||
* Fix fallback to GLES2 [Adam; #635]
|
||||
* Fix interoperation with wl_data_device_manager v1 [Carlos; #965]
|
||||
* Fix visual glitches with offscreen effects applied [Georges; !992]
|
||||
* Favor text over images in clipboard manager [Carlos; #919]
|
||||
* Fixes crashes [Jonas, Carlos; !961, !869]
|
||||
* Plugged memory leaks [Sebastian, Adam; !1002, !1011]
|
||||
* Misc. bug fixes [Carlos, Robert, Olivier; !1005, #878, !1031, !1034, !1040]
|
||||
|
||||
Contributors:
|
||||
Olivier Fourdan, Carlos Garnacho, Adam Jackson, Sebastian Keller,
|
||||
Robert Mader, Georges Basile Stavracas Neto, Jonas Ådahl
|
||||
|
||||
Translators:
|
||||
Umarzuki Bin Mochlis Moktar [ms]
|
||||
|
||||
3.34.3
|
||||
======
|
||||
* Fix window recording on HiDPI [Pascal; !976]
|
||||
* Fix top-left pixel being insensitive to clicks [Sebastian; #893]
|
||||
|
||||
Contributors:
|
||||
Sebastian Keller, Pascal Nowack
|
||||
|
||||
3.34.2
|
||||
======
|
||||
* Fix immediate screen blank after releasing inhibitor [Tim; #573]
|
||||
|
||||
@@ -121,12 +121,12 @@ G_DEFINE_TYPE (ClutterBrightnessContrastEffect,
|
||||
static gboolean
|
||||
will_have_no_effect (ClutterBrightnessContrastEffect *self)
|
||||
{
|
||||
return (self->brightness_red == no_change &&
|
||||
self->brightness_green == no_change &&
|
||||
self->brightness_blue == no_change &&
|
||||
self->contrast_red == no_change &&
|
||||
self->contrast_green == no_change &&
|
||||
self->contrast_blue == no_change);
|
||||
return (G_APPROX_VALUE (self->brightness_red, no_change, FLT_EPSILON) &&
|
||||
G_APPROX_VALUE (self->brightness_green, no_change, FLT_EPSILON) &&
|
||||
G_APPROX_VALUE (self->brightness_blue, no_change, FLT_EPSILON) &&
|
||||
G_APPROX_VALUE (self->contrast_red, no_change, FLT_EPSILON) &&
|
||||
G_APPROX_VALUE (self->contrast_green, no_change, FLT_EPSILON) &&
|
||||
G_APPROX_VALUE (self->contrast_blue, no_change, FLT_EPSILON));
|
||||
}
|
||||
|
||||
static gboolean
|
||||
@@ -494,9 +494,9 @@ clutter_brightness_contrast_effect_set_brightness_full (ClutterBrightnessContras
|
||||
{
|
||||
g_return_if_fail (CLUTTER_IS_BRIGHTNESS_CONTRAST_EFFECT (effect));
|
||||
|
||||
if (red == effect->brightness_red &&
|
||||
green == effect->brightness_green &&
|
||||
blue == effect->brightness_blue)
|
||||
if (G_APPROX_VALUE (red, effect->brightness_red, FLT_EPSILON) &&
|
||||
G_APPROX_VALUE (green, effect->brightness_green, FLT_EPSILON) &&
|
||||
G_APPROX_VALUE (blue, effect->brightness_blue, FLT_EPSILON))
|
||||
return;
|
||||
|
||||
effect->brightness_red = red;
|
||||
@@ -584,9 +584,9 @@ clutter_brightness_contrast_effect_set_contrast_full (ClutterBrightnessContrastE
|
||||
{
|
||||
g_return_if_fail (CLUTTER_IS_BRIGHTNESS_CONTRAST_EFFECT (effect));
|
||||
|
||||
if (red == effect->contrast_red &&
|
||||
green == effect->contrast_green &&
|
||||
blue == effect->contrast_blue)
|
||||
if (G_APPROX_VALUE (red, effect->contrast_red, FLT_EPSILON) &&
|
||||
G_APPROX_VALUE (green, effect->contrast_green, FLT_EPSILON) &&
|
||||
G_APPROX_VALUE (blue, effect->contrast_blue, FLT_EPSILON))
|
||||
return;
|
||||
|
||||
effect->contrast_red = red;
|
||||
|
||||
@@ -117,11 +117,7 @@ clutter_offscreen_effect_set_actor (ClutterActorMeta *meta,
|
||||
meta_class->set_actor (meta, actor);
|
||||
|
||||
/* clear out the previous state */
|
||||
if (priv->offscreen != NULL)
|
||||
{
|
||||
cogl_handle_unref (priv->offscreen);
|
||||
priv->offscreen = NULL;
|
||||
}
|
||||
g_clear_pointer (&priv->offscreen, cogl_object_unref);
|
||||
|
||||
/* we keep a back pointer here, to avoid going through the ActorMeta */
|
||||
priv->actor = clutter_actor_meta_get_actor (meta);
|
||||
@@ -197,17 +193,8 @@ update_fbo (ClutterEffect *effect,
|
||||
ensure_pipeline_filter_for_scale (self, resource_scale);
|
||||
}
|
||||
|
||||
if (priv->texture != NULL)
|
||||
{
|
||||
cogl_handle_unref (priv->texture);
|
||||
priv->texture = NULL;
|
||||
}
|
||||
|
||||
if (priv->offscreen != NULL)
|
||||
{
|
||||
cogl_handle_unref (priv->offscreen);
|
||||
priv->offscreen = NULL;
|
||||
}
|
||||
g_clear_pointer (&priv->texture, cogl_object_unref);
|
||||
g_clear_pointer (&priv->offscreen, cogl_object_unref);
|
||||
|
||||
priv->texture =
|
||||
clutter_offscreen_effect_create_texture (self, target_width, target_height);
|
||||
@@ -471,29 +458,44 @@ clutter_offscreen_effect_paint (ClutterEffect *effect,
|
||||
*/
|
||||
if (priv->offscreen == NULL || (flags & CLUTTER_EFFECT_PAINT_ACTOR_DIRTY))
|
||||
{
|
||||
/* Chain up to the parent paint method which will call the pre and
|
||||
post paint functions to update the image */
|
||||
CLUTTER_EFFECT_CLASS (clutter_offscreen_effect_parent_class)->
|
||||
paint (effect, flags);
|
||||
ClutterEffectClass *effect_class = CLUTTER_EFFECT_GET_CLASS (effect);
|
||||
gboolean pre_paint_succeeded;
|
||||
|
||||
pre_paint_succeeded = effect_class->pre_paint (effect);
|
||||
|
||||
clutter_actor_continue_paint (priv->actor);
|
||||
|
||||
if (pre_paint_succeeded)
|
||||
effect_class->post_paint (effect);
|
||||
else
|
||||
g_clear_pointer (&priv->offscreen, cogl_object_unref);
|
||||
}
|
||||
else
|
||||
clutter_offscreen_effect_paint_texture (self);
|
||||
}
|
||||
|
||||
static void
|
||||
clutter_offscreen_effect_notify (GObject *gobject,
|
||||
GParamSpec *pspec)
|
||||
{
|
||||
ClutterOffscreenEffect *offscreen_effect = CLUTTER_OFFSCREEN_EFFECT (gobject);
|
||||
ClutterOffscreenEffectPrivate *priv = offscreen_effect->priv;
|
||||
|
||||
if (strcmp (pspec->name, "enabled") == 0)
|
||||
g_clear_pointer (&priv->offscreen, cogl_object_unref);
|
||||
|
||||
G_OBJECT_CLASS (clutter_offscreen_effect_parent_class)->notify (gobject, pspec);
|
||||
}
|
||||
|
||||
static void
|
||||
clutter_offscreen_effect_finalize (GObject *gobject)
|
||||
{
|
||||
ClutterOffscreenEffect *self = CLUTTER_OFFSCREEN_EFFECT (gobject);
|
||||
ClutterOffscreenEffectPrivate *priv = self->priv;
|
||||
|
||||
if (priv->offscreen)
|
||||
cogl_handle_unref (priv->offscreen);
|
||||
|
||||
if (priv->target)
|
||||
cogl_handle_unref (priv->target);
|
||||
|
||||
if (priv->texture)
|
||||
cogl_handle_unref (priv->texture);
|
||||
g_clear_pointer (&priv->offscreen, cogl_object_unref);
|
||||
g_clear_pointer (&priv->texture, cogl_object_unref);
|
||||
g_clear_pointer (&priv->target, cogl_object_unref);
|
||||
|
||||
G_OBJECT_CLASS (clutter_offscreen_effect_parent_class)->finalize (gobject);
|
||||
}
|
||||
@@ -515,6 +517,7 @@ clutter_offscreen_effect_class_init (ClutterOffscreenEffectClass *klass)
|
||||
effect_class->paint = clutter_offscreen_effect_paint;
|
||||
|
||||
gobject_class->finalize = clutter_offscreen_effect_finalize;
|
||||
gobject_class->notify = clutter_offscreen_effect_notify;
|
||||
}
|
||||
|
||||
static void
|
||||
|
||||
@@ -486,9 +486,9 @@ is_inside_axis_aligned_rectangle (const ClutterPoint *point,
|
||||
const ClutterPoint *vertices)
|
||||
{
|
||||
float min_x = FLT_MAX;
|
||||
float max_x = FLT_MIN;
|
||||
float max_x = -FLT_MAX;
|
||||
float min_y = FLT_MAX;
|
||||
float max_y = FLT_MIN;
|
||||
float max_y = -FLT_MAX;
|
||||
int i;
|
||||
|
||||
for (i = 0; i < 3; i++)
|
||||
|
||||
@@ -329,6 +329,8 @@ try_create_context (CoglDisplay *display,
|
||||
if (renderer->driver == COGL_DRIVER_GL ||
|
||||
renderer->driver == COGL_DRIVER_GL3)
|
||||
eglBindAPI (EGL_OPENGL_API);
|
||||
else if (renderer->driver == COGL_DRIVER_GLES2)
|
||||
eglBindAPI (EGL_OPENGL_ES_API);
|
||||
|
||||
egl_attributes_from_framebuffer_config (display,
|
||||
&display->onscreen_template->config,
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
project('mutter', 'c',
|
||||
version: '3.34.2',
|
||||
version: '3.34.6',
|
||||
meson_version: '>= 0.50.0',
|
||||
license: 'GPLv2+'
|
||||
)
|
||||
|
||||
158
po/zh_TW.po
158
po/zh_TW.po
@@ -10,8 +10,8 @@ msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: metacity 3.3.4\n"
|
||||
"Report-Msgid-Bugs-To: https://gitlab.gnome.org/GNOME/mutter/issues\n"
|
||||
"POT-Creation-Date: 2019-02-04 17:52+0000\n"
|
||||
"PO-Revision-Date: 2019-02-17 23:15+0800\n"
|
||||
"POT-Creation-Date: 2019-11-21 15:22+0000\n"
|
||||
"PO-Revision-Date: 2019-11-23 13:58+0800\n"
|
||||
"Last-Translator: pan93412 <pan93412@gmail.com>\n"
|
||||
"Language-Team: Chinese <zh-l10n@linux.org.tw>\n"
|
||||
"Language: zh_TW\n"
|
||||
@@ -19,7 +19,7 @@ msgstr ""
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"Plural-Forms: nplurals=1; plural=0;\n"
|
||||
"X-Generator: Lokalize 18.12.2\n"
|
||||
"X-Generator: Lokalize 19.11.80\n"
|
||||
|
||||
#: data/50-mutter-navigation.xml:6
|
||||
msgid "Navigation"
|
||||
@@ -371,6 +371,16 @@ msgid "Enable experimental features"
|
||||
msgstr "啟用試驗性功能"
|
||||
|
||||
#: data/org.gnome.mutter.gschema.xml.in:108
|
||||
#| msgid ""
|
||||
#| "To enable experimental features, add the feature keyword to the list. "
|
||||
#| "Whether the feature requires restarting the compositor depends on the "
|
||||
#| "given feature. Any experimental feature is not required to still be "
|
||||
#| "available, or configurable. Don’t expect adding anything in this setting "
|
||||
#| "to be future proof. Currently possible keywords: • “scale-monitor-"
|
||||
#| "framebuffer” — makes mutter default to layout logical monitors in a "
|
||||
#| "logical pixel coordinate space, while scaling monitor framebuffers "
|
||||
#| "instead of window content, to manage HiDPI monitors. Does not require a "
|
||||
#| "restart."
|
||||
msgid ""
|
||||
"To enable experimental features, add the feature keyword to the list. "
|
||||
"Whether the feature requires restarting the compositor depends on the given "
|
||||
@@ -379,27 +389,41 @@ msgid ""
|
||||
"proof. Currently possible keywords: • “scale-monitor-framebuffer” — makes "
|
||||
"mutter default to layout logical monitors in a logical pixel coordinate "
|
||||
"space, while scaling monitor framebuffers instead of window content, to "
|
||||
"manage HiDPI monitors. Does not require a restart."
|
||||
"manage HiDPI monitors. Does not require a restart. • “rt-scheduler” — makes "
|
||||
"mutter request a low priority real-time scheduling. The executable or user "
|
||||
"must have CAP_SYS_NICE. Requires a restart. • “autostart-xwayland” — "
|
||||
"initializes Xwayland lazily if there are X11 clients. Requires restart."
|
||||
msgstr ""
|
||||
"若要啟用實驗性功能,請將功能關鍵字加入列表中。置於該功能是否須要重新啟動混成"
|
||||
"器則視給予的功能而定。任何實驗性功能不一定能用、或是可以調整設定。請不要預期"
|
||||
"在此設定中加入的任何東西未來都能存在。目前可用的關鍵字有: • “scale-monitor-"
|
||||
"framebuffer” — 讓 mutter 預設採用邏輯像素座標空間的配置邏輯螢幕,而縮放螢幕 "
|
||||
"framebuffer 則取代視窗內容以管理 HiDPI 螢幕。不須要重新啟動。"
|
||||
"在此設定中加入的任何東西未來都能存在。目前可用的關鍵字有:"
|
||||
"• 「scale-monitor-framebuffer」— 讓 mutter 預設採用邏輯像素座標空間的"
|
||||
"配置邏輯螢幕,而縮放螢幕 framebuffer 則取代視窗內容以管理 HiDPI 螢幕。不需要重新啟動。"
|
||||
"• 「rt-scheduler」— 讓 mutter 請求低優先級的即時排程。可執行檔或使用者必須要有"
|
||||
"CAP_SYS_NICE。需要重新啟動。"
|
||||
"• 「autostart-xwayland」— 如果有 X11 用戶端就延遲初始化 Xwayland。需要重新啟動。"
|
||||
|
||||
#: data/org.gnome.mutter.gschema.xml.in:141
|
||||
#: data/org.gnome.mutter.gschema.xml.in:134
|
||||
msgid "Modifier to use to locate the pointer"
|
||||
msgstr "要用來定位指標的輔助鍵"
|
||||
|
||||
#: data/org.gnome.mutter.gschema.xml.in:135
|
||||
msgid "This key will initiate the “locate pointer” action."
|
||||
msgstr "這個按鍵將會「定位指標」。"
|
||||
|
||||
#: data/org.gnome.mutter.gschema.xml.in:155
|
||||
msgid "Select window from tab popup"
|
||||
msgstr "從分頁彈出項選擇視窗"
|
||||
|
||||
#: data/org.gnome.mutter.gschema.xml.in:146
|
||||
#: data/org.gnome.mutter.gschema.xml.in:160
|
||||
msgid "Cancel tab popup"
|
||||
msgstr "取消分頁彈出項"
|
||||
|
||||
#: data/org.gnome.mutter.gschema.xml.in:151
|
||||
#: data/org.gnome.mutter.gschema.xml.in:165
|
||||
msgid "Switch monitor configurations"
|
||||
msgstr "切換螢幕組態"
|
||||
|
||||
#: data/org.gnome.mutter.gschema.xml.in:156
|
||||
#: data/org.gnome.mutter.gschema.xml.in:170
|
||||
msgid "Rotates the built-in monitor configuration"
|
||||
msgstr "旋轉切換內建螢幕組態"
|
||||
|
||||
@@ -456,26 +480,38 @@ msgid "Re-enable shortcuts"
|
||||
msgstr "重新啟用快捷鍵"
|
||||
|
||||
#: data/org.gnome.mutter.wayland.gschema.xml.in:64
|
||||
msgid "Allow grabs with Xwayland"
|
||||
msgstr "在 Xwayland 允許抓取"
|
||||
#| msgid "Allow grabs with Xwayland"
|
||||
msgid "Allow X11 grabs to lock keyboard focus with Xwayland"
|
||||
msgstr "允許 X11 抓取以使用 Xwayland 鎖定鍵盤焦點"
|
||||
|
||||
#: data/org.gnome.mutter.wayland.gschema.xml.in:65
|
||||
#, fuzzy
|
||||
#| msgid ""
|
||||
#| "Allow keyboard grabs issued by X11 applications running in Xwayland to be "
|
||||
#| "taken into account. For a X11 grab to be taken into account under "
|
||||
#| "Wayland, the client must also either send a specific X11 ClientMessage to "
|
||||
#| "the root window or be among the applications white-listed in key "
|
||||
#| "“xwayland-grab-access-rules”."
|
||||
msgid ""
|
||||
"Allow keyboard grabs issued by X11 applications running in Xwayland to be "
|
||||
"taken into account. For a X11 grab to be taken into account under Wayland, "
|
||||
"the client must also either send a specific X11 ClientMessage to the root "
|
||||
"window or be among the applications white-listed in key “xwayland-grab-"
|
||||
"access-rules”."
|
||||
"Allow all keyboard events to be routed to X11 “override redirect” windows "
|
||||
"with a grab when running in Xwayland. This option is to support X11 clients "
|
||||
"which map an “override redirect” window (which do not receive keyboard "
|
||||
"focus) and issue a keyboard grab to force all keyboard events to that "
|
||||
"window. This option is seldom used and has no effect on regular X11 windows "
|
||||
"which can receive keyboard focus under normal circumstances. For a X11 grab "
|
||||
"to be taken into account under Wayland, the client must also either send a "
|
||||
"specific X11 ClientMessage to the root window or be among the applications "
|
||||
"white-listed in key “xwayland-grab-access-rules”."
|
||||
msgstr ""
|
||||
"考慮到在 Xwayland 中執行的 X11 應用程序發出的鍵盤抓取。對於在 Wayland 下考慮"
|
||||
"的 X11 抓取,客戶端也必須送出一個特定的 X11 ClientMessage 到 root 視窗或者在 "
|
||||
"xwayland-grab-access-rules 鍵白名單其中的應用程式。"
|
||||
"xwayland-grab-access-rules 鍵白名單其中的應用程式"
|
||||
|
||||
#: data/org.gnome.mutter.wayland.gschema.xml.in:77
|
||||
#: data/org.gnome.mutter.wayland.gschema.xml.in:84
|
||||
msgid "Xwayland applications allowed to issue keyboard grabs"
|
||||
msgstr "Xwayland 應用程式允許發出鍵盤抓取"
|
||||
|
||||
#: data/org.gnome.mutter.wayland.gschema.xml.in:78
|
||||
#: data/org.gnome.mutter.wayland.gschema.xml.in:85
|
||||
msgid ""
|
||||
"List the resource names or resource class of X11 windows either allowed or "
|
||||
"not allowed to issue X11 keyboard grabs under Xwayland. The resource name or "
|
||||
@@ -499,7 +535,7 @@ msgstr ""
|
||||
#. TRANSLATORS: This string refers to a button that switches between
|
||||
#. * different modes.
|
||||
#.
|
||||
#: src/backends/meta-input-settings.c:2423
|
||||
#: src/backends/meta-input-settings.c:2532
|
||||
#, c-format
|
||||
msgid "Mode Switch (Group %d)"
|
||||
msgstr "模式切換( 群組 %d)"
|
||||
@@ -507,121 +543,124 @@ msgstr "模式切換( 群組 %d)"
|
||||
#. TRANSLATORS: This string refers to an action, cycles drawing tablets'
|
||||
#. * mapping through the available outputs.
|
||||
#.
|
||||
#: src/backends/meta-input-settings.c:2446
|
||||
#: src/backends/meta-input-settings.c:2555
|
||||
msgid "Switch monitor"
|
||||
msgstr "切換螢幕"
|
||||
|
||||
#: src/backends/meta-input-settings.c:2448
|
||||
#: src/backends/meta-input-settings.c:2557
|
||||
msgid "Show on-screen help"
|
||||
msgstr "顯示螢幕求助"
|
||||
|
||||
#: src/backends/meta-monitor-manager.c:954
|
||||
#: src/backends/meta-monitor.c:223
|
||||
msgid "Built-in display"
|
||||
msgstr "內建顯示"
|
||||
|
||||
#: src/backends/meta-monitor-manager.c:986
|
||||
#: src/backends/meta-monitor.c:252
|
||||
msgid "Unknown"
|
||||
msgstr "不明"
|
||||
|
||||
#: src/backends/meta-monitor-manager.c:988
|
||||
#: src/backends/meta-monitor.c:254
|
||||
msgid "Unknown Display"
|
||||
msgstr "不明的顯示器"
|
||||
|
||||
#: src/backends/meta-monitor-manager.c:996
|
||||
#: src/backends/meta-monitor.c:262
|
||||
#, c-format
|
||||
#| msgid "%s %s"
|
||||
msgctxt ""
|
||||
"This is a monitor vendor name, followed by a size in inches, like 'Dell 15\"'"
|
||||
msgid "%s %s"
|
||||
msgstr "%s %s"
|
||||
|
||||
#: src/backends/meta-monitor-manager.c:1004
|
||||
#: src/backends/meta-monitor.c:270
|
||||
#, c-format
|
||||
#| msgid "%s %s"
|
||||
msgctxt ""
|
||||
"This is a monitor vendor name followed by product/model name where size in "
|
||||
"inches could not be calculated, e.g. Dell U2414H"
|
||||
msgid "%s %s"
|
||||
msgstr "%s %s"
|
||||
|
||||
#. Translators: this string will appear in Sysprof
|
||||
#: src/backends/meta-profiler.c:82
|
||||
msgid "Compositor"
|
||||
msgstr "合成器"
|
||||
|
||||
# FIXME: I'm still unclear about the meaning of XGetSelectionOwner -- Abel
|
||||
#. This probably means that a non-WM compositor like xcompmgr is running;
|
||||
#. * we have no way to get it to exit
|
||||
#: src/compositor/compositor.c:482
|
||||
#: src/compositor/compositor.c:509
|
||||
#, c-format
|
||||
msgid ""
|
||||
"Another compositing manager is already running on screen %i on display “%s”."
|
||||
msgstr "在畫面「%2$s」中的第 %1$i 個螢幕中已啟動另一個組合視窗管理員。"
|
||||
|
||||
#: src/core/bell.c:252
|
||||
#: src/core/bell.c:192
|
||||
msgid "Bell event"
|
||||
msgstr "響鈴事件"
|
||||
|
||||
#: src/core/main.c:185
|
||||
#: src/core/main.c:190
|
||||
msgid "Disable connection to session manager"
|
||||
msgstr "停用到作業階段管理員的連線"
|
||||
|
||||
#: src/core/main.c:191
|
||||
#: src/core/main.c:196
|
||||
msgid "Replace the running window manager"
|
||||
msgstr "取代執行中的視窗管理員"
|
||||
|
||||
#: src/core/main.c:197
|
||||
#: src/core/main.c:202
|
||||
msgid "Specify session management ID"
|
||||
msgstr "指定作業階段管理 ID"
|
||||
|
||||
#: src/core/main.c:202
|
||||
#: src/core/main.c:207
|
||||
msgid "X Display to use"
|
||||
msgstr "使用的 X 畫面"
|
||||
|
||||
#: src/core/main.c:208
|
||||
#: src/core/main.c:213
|
||||
msgid "Initialize session from savefile"
|
||||
msgstr "以 savefile 初始化作業階段"
|
||||
|
||||
#: src/core/main.c:214
|
||||
#: src/core/main.c:219
|
||||
msgid "Make X calls synchronous"
|
||||
msgstr "使用同步方式調用 X 函式"
|
||||
|
||||
#: src/core/main.c:221
|
||||
#: src/core/main.c:226
|
||||
msgid "Run as a wayland compositor"
|
||||
msgstr "以 wayland 組合器執行"
|
||||
|
||||
#: src/core/main.c:227
|
||||
#: src/core/main.c:232
|
||||
msgid "Run as a nested compositor"
|
||||
msgstr "以巢狀組合器執行"
|
||||
|
||||
#: src/core/main.c:233
|
||||
#: src/core/main.c:238
|
||||
msgid "Run wayland compositor without starting Xwayland"
|
||||
msgstr "在不啟動 Xwayland 的情況下開啟 Wayland 合成器"
|
||||
|
||||
#: src/core/main.c:241
|
||||
#: src/core/main.c:246
|
||||
msgid "Run as a full display server, rather than nested"
|
||||
msgstr "以完全顯示伺服器執行,而非巢狀"
|
||||
|
||||
#: src/core/main.c:247
|
||||
#: src/core/main.c:252
|
||||
msgid "Run with X11 backend"
|
||||
msgstr "透過 X11 後端執行"
|
||||
|
||||
#. Translators: %s is a window title
|
||||
#: src/core/meta-close-dialog-default.c:150
|
||||
#: src/core/meta-close-dialog-default.c:151
|
||||
#, c-format
|
||||
msgid "“%s” is not responding."
|
||||
msgstr "「%s」沒有回應。"
|
||||
|
||||
#: src/core/meta-close-dialog-default.c:152
|
||||
#: src/core/meta-close-dialog-default.c:153
|
||||
msgid "Application is not responding."
|
||||
msgstr "應用程式沒有回應。"
|
||||
|
||||
#: src/core/meta-close-dialog-default.c:157
|
||||
#: src/core/meta-close-dialog-default.c:158
|
||||
msgid ""
|
||||
"You may choose to wait a short while for it to continue or force the "
|
||||
"application to quit entirely."
|
||||
msgstr "您可以選擇稍等一下讓它繼續,或者強制完全退出程式。"
|
||||
|
||||
#: src/core/meta-close-dialog-default.c:164
|
||||
#: src/core/meta-close-dialog-default.c:165
|
||||
msgid "_Force Quit"
|
||||
msgstr "強制退出(_F)"
|
||||
|
||||
#: src/core/meta-close-dialog-default.c:164
|
||||
#: src/core/meta-close-dialog-default.c:165
|
||||
msgid "_Wait"
|
||||
msgstr "等待(_W)"
|
||||
|
||||
@@ -648,21 +687,21 @@ msgid "Mutter plugin to use"
|
||||
msgstr "要使用的 Mutter 外掛程式"
|
||||
|
||||
# (Abel) take care of the same string in libwnck
|
||||
#: src/core/prefs.c:1786
|
||||
#: src/core/prefs.c:1849
|
||||
#, c-format
|
||||
msgid "Workspace %d"
|
||||
msgstr "工作區 %d"
|
||||
|
||||
#: src/core/util.c:121
|
||||
#: src/core/util.c:122
|
||||
msgid "Mutter was compiled without support for verbose mode\n"
|
||||
msgstr "編譯 Mutter 時並沒有加入詳細偵錯模式的支援\n"
|
||||
|
||||
#: src/wayland/meta-wayland-tablet-pad.c:567
|
||||
#: src/wayland/meta-wayland-tablet-pad.c:568
|
||||
#, c-format
|
||||
msgid "Mode Switch: Mode %d"
|
||||
msgstr "模式切換:模式 %d"
|
||||
|
||||
#: src/x11/meta-x11-display.c:666
|
||||
#: src/x11/meta-x11-display.c:679
|
||||
#, c-format
|
||||
msgid ""
|
||||
"Display “%s” already has a window manager; try using the --replace option to "
|
||||
@@ -671,27 +710,32 @@ msgstr ""
|
||||
"畫面「%s」已經有了視窗管理員;請嘗試使用 --replace 選項來替換目前的視窗管理"
|
||||
"員。"
|
||||
|
||||
#: src/x11/meta-x11-display.c:1008
|
||||
#: src/x11/meta-x11-display.c:1040
|
||||
msgid "Failed to initialize GDK\n"
|
||||
msgstr "無法初始化 GDK\n"
|
||||
|
||||
#: src/x11/meta-x11-display.c:1032
|
||||
#: src/x11/meta-x11-display.c:1064
|
||||
#, c-format
|
||||
msgid "Failed to open X Window System display “%s”\n"
|
||||
msgstr "無法開啟 X Window 系統畫面「%s」\n"
|
||||
|
||||
#: src/x11/meta-x11-display.c:1115
|
||||
#: src/x11/meta-x11-display.c:1147
|
||||
#, c-format
|
||||
msgid "Screen %d on display “%s” is invalid\n"
|
||||
msgstr "畫面「%2$s」中的第 %1$d 個螢幕無效\n"
|
||||
|
||||
#: src/x11/meta-x11-selection-input-stream.c:445
|
||||
#, c-format
|
||||
msgid "Format %s not supported"
|
||||
msgstr "不支援 %s 格式"
|
||||
|
||||
#: src/x11/session.c:1821
|
||||
msgid ""
|
||||
"These windows do not support “save current setup” and will have to be "
|
||||
"restarted manually next time you log in."
|
||||
msgstr "這些視窗不支援「儲存目前的設定」,必須在下次登入後自行啟動。"
|
||||
|
||||
#: src/x11/window-props.c:568
|
||||
#: src/x11/window-props.c:569
|
||||
#, c-format
|
||||
msgid "%s (on %s)"
|
||||
msgstr "%s(在 %s)"
|
||||
|
||||
@@ -226,11 +226,15 @@ meta_screen_cast_window_stream_initable_init (GInitable *initable,
|
||||
G_CALLBACK (on_window_unmanaged),
|
||||
window_stream);
|
||||
|
||||
if (meta_is_stage_views_scaled ())
|
||||
scale = (int) ceilf (meta_logical_monitor_get_scale (logical_monitor));
|
||||
else
|
||||
scale = 1;
|
||||
|
||||
/* We cannot set the stream size to the exact size of the window, because
|
||||
* windows can be resized, whereas streams cannot.
|
||||
* So we set a size equals to the size of the logical monitor for the window.
|
||||
*/
|
||||
scale = (int) ceil (meta_logical_monitor_get_scale (logical_monitor));
|
||||
window_stream->logical_width = logical_monitor->rect.width;
|
||||
window_stream->logical_height = logical_monitor->rect.height;
|
||||
window_stream->stream_width = logical_monitor->rect.width * scale;
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
|
||||
/*
|
||||
* Copyright (C) 2014 Red Hat
|
||||
* Copyright 2020 DisplayLink (UK) Ltd.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License as
|
||||
@@ -1176,6 +1177,42 @@ on_monitors_changed (MetaMonitorManager *monitors,
|
||||
force_update_hw_cursor (native);
|
||||
}
|
||||
|
||||
static void
|
||||
init_hw_cursor_support_for_gpu (MetaGpuKms *gpu_kms)
|
||||
{
|
||||
MetaCursorRendererNativeGpuData *cursor_renderer_gpu_data;
|
||||
int kms_fd;
|
||||
struct gbm_device *gbm_device;
|
||||
uint64_t width, height;
|
||||
|
||||
gbm_device = meta_gbm_device_from_gpu (gpu_kms);
|
||||
if (!gbm_device)
|
||||
return;
|
||||
|
||||
cursor_renderer_gpu_data =
|
||||
meta_create_cursor_renderer_native_gpu_data (gpu_kms);
|
||||
|
||||
kms_fd = meta_gpu_kms_get_fd (gpu_kms);
|
||||
if (drmGetCap (kms_fd, DRM_CAP_CURSOR_WIDTH, &width) == 0 &&
|
||||
drmGetCap (kms_fd, DRM_CAP_CURSOR_HEIGHT, &height) == 0)
|
||||
{
|
||||
cursor_renderer_gpu_data->cursor_width = width;
|
||||
cursor_renderer_gpu_data->cursor_height = height;
|
||||
}
|
||||
else
|
||||
{
|
||||
cursor_renderer_gpu_data->cursor_width = 64;
|
||||
cursor_renderer_gpu_data->cursor_height = 64;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
on_gpu_added_for_cursor (MetaBackend *backend,
|
||||
MetaGpuKms *gpu_kms)
|
||||
{
|
||||
init_hw_cursor_support_for_gpu (gpu_kms);
|
||||
}
|
||||
|
||||
static void
|
||||
init_hw_cursor_support (MetaCursorRendererNative *cursor_renderer_native)
|
||||
{
|
||||
@@ -1188,30 +1225,8 @@ init_hw_cursor_support (MetaCursorRendererNative *cursor_renderer_native)
|
||||
for (l = gpus; l; l = l->next)
|
||||
{
|
||||
MetaGpuKms *gpu_kms = l->data;
|
||||
MetaCursorRendererNativeGpuData *cursor_renderer_gpu_data;
|
||||
int kms_fd;
|
||||
struct gbm_device *gbm_device;
|
||||
uint64_t width, height;
|
||||
|
||||
gbm_device = meta_gbm_device_from_gpu (gpu_kms);
|
||||
if (!gbm_device)
|
||||
continue;
|
||||
|
||||
cursor_renderer_gpu_data =
|
||||
meta_create_cursor_renderer_native_gpu_data (gpu_kms);
|
||||
|
||||
kms_fd = meta_gpu_kms_get_fd (gpu_kms);
|
||||
if (drmGetCap (kms_fd, DRM_CAP_CURSOR_WIDTH, &width) == 0 &&
|
||||
drmGetCap (kms_fd, DRM_CAP_CURSOR_HEIGHT, &height) == 0)
|
||||
{
|
||||
cursor_renderer_gpu_data->cursor_width = width;
|
||||
cursor_renderer_gpu_data->cursor_height = height;
|
||||
}
|
||||
else
|
||||
{
|
||||
cursor_renderer_gpu_data->cursor_width = 64;
|
||||
cursor_renderer_gpu_data->cursor_height = 64;
|
||||
}
|
||||
init_hw_cursor_support_for_gpu (gpu_kms);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1231,6 +1246,8 @@ meta_cursor_renderer_native_new (MetaBackend *backend)
|
||||
g_signal_connect_object (monitor_manager, "monitors-changed-internal",
|
||||
G_CALLBACK (on_monitors_changed),
|
||||
cursor_renderer_native, 0);
|
||||
g_signal_connect (backend, "gpu-added",
|
||||
G_CALLBACK (on_gpu_added_for_cursor), NULL);
|
||||
|
||||
priv->backend = backend;
|
||||
priv->hw_state_invalidated = TRUE;
|
||||
|
||||
@@ -326,6 +326,16 @@ meta_kms_impl_device_update_states (MetaKmsImplDevice *impl_device)
|
||||
meta_assert_in_kms_impl (meta_kms_impl_get_kms (impl_device->impl));
|
||||
|
||||
drm_resources = drmModeGetResources (impl_device->fd);
|
||||
if (!drm_resources)
|
||||
{
|
||||
g_list_free_full (impl_device->planes, g_object_unref);
|
||||
g_list_free_full (impl_device->crtcs, g_object_unref);
|
||||
g_list_free_full (impl_device->connectors, g_object_unref);
|
||||
impl_device->planes = NULL;
|
||||
impl_device->crtcs = NULL;
|
||||
impl_device->connectors = NULL;
|
||||
return;
|
||||
}
|
||||
|
||||
update_connectors (impl_device, drm_resources);
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
* Copyright (C) 2018-2019 Red Hat
|
||||
* Copyright (C) 2019 DisplayLink (UK) Ltd.
|
||||
* Copyright (C) 2019-2020 DisplayLink (UK) Ltd.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License as
|
||||
@@ -247,7 +247,8 @@ process_mode_set (MetaKmsImpl *impl,
|
||||
if (ret != 0)
|
||||
{
|
||||
g_set_error (error, G_IO_ERROR, g_io_error_from_errno (-ret),
|
||||
"Failed to set mode on CRTC %u: %s",
|
||||
"Failed to set mode %s on CRTC %u: %s",
|
||||
mode_set->drm_mode ? mode_set->drm_mode->name : "off",
|
||||
meta_kms_crtc_get_id (crtc),
|
||||
g_strerror (-ret));
|
||||
return FALSE;
|
||||
@@ -323,6 +324,13 @@ retry_page_flip_data_free (RetryPageFlipData *retry_page_flip_data)
|
||||
g_free (retry_page_flip_data);
|
||||
}
|
||||
|
||||
static CachedModeSet *
|
||||
get_cached_mode_set (MetaKmsImplSimple *impl_simple,
|
||||
MetaKmsCrtc *crtc)
|
||||
{
|
||||
return g_hash_table_lookup (impl_simple->cached_mode_sets, crtc);
|
||||
}
|
||||
|
||||
static float
|
||||
get_cached_crtc_refresh_rate (MetaKmsImplSimple *impl_simple,
|
||||
MetaKmsCrtc *crtc)
|
||||
@@ -642,16 +650,35 @@ process_page_flip (MetaKmsImpl *impl,
|
||||
meta_kms_page_flip_data_ref (page_flip_data));
|
||||
}
|
||||
|
||||
if (ret != 0)
|
||||
meta_kms_page_flip_data_unref (page_flip_data);
|
||||
|
||||
if (ret == -EBUSY)
|
||||
{
|
||||
float refresh_rate;
|
||||
CachedModeSet *cached_mode_set;
|
||||
|
||||
refresh_rate = get_cached_crtc_refresh_rate (impl_simple, crtc);
|
||||
schedule_retry_page_flip (impl_simple,
|
||||
crtc,
|
||||
plane_assignment->fb_id,
|
||||
refresh_rate,
|
||||
page_flip_data);
|
||||
cached_mode_set = get_cached_mode_set (impl_simple, crtc);
|
||||
if (cached_mode_set)
|
||||
{
|
||||
drmModeModeInfo *drm_mode;
|
||||
float refresh_rate;
|
||||
|
||||
drm_mode = cached_mode_set->drm_mode;
|
||||
refresh_rate = meta_calculate_drm_mode_refresh_rate (drm_mode);
|
||||
schedule_retry_page_flip (impl_simple,
|
||||
crtc,
|
||||
plane_assignment->fb_id,
|
||||
refresh_rate,
|
||||
page_flip_data);
|
||||
}
|
||||
else
|
||||
{
|
||||
g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED,
|
||||
"Page flip of %u failed, and no mode set available",
|
||||
meta_kms_crtc_get_id (crtc));
|
||||
meta_kms_page_flip_data_unref (page_flip_data);
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
else if (ret == -EINVAL)
|
||||
{
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
/*
|
||||
* Copyright (C) 2018 Red Hat
|
||||
* Copyright 2020 DisplayLink (UK) Ltd.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License as
|
||||
@@ -385,6 +386,7 @@ meta_kms_add_source_in_impl (MetaKms *kms,
|
||||
simple_impl_source->kms = kms;
|
||||
|
||||
g_source_set_callback (source, func, user_data, user_data_destroy);
|
||||
g_source_set_ready_time (source, 0);
|
||||
g_source_attach (source, g_main_context_get_thread_default ());
|
||||
|
||||
return source;
|
||||
|
||||
@@ -82,6 +82,9 @@ paint_egl_image (MetaGles3 *gles3,
|
||||
0, 0, width, height,
|
||||
GL_COLOR_BUFFER_BIT,
|
||||
GL_NEAREST));
|
||||
|
||||
GLBAS (gles3, glDeleteTextures, (1, &texture));
|
||||
GLBAS (gles3, glDeleteFramebuffers, (1, &framebuffer));
|
||||
}
|
||||
|
||||
gboolean
|
||||
|
||||
@@ -859,6 +859,7 @@ meta_backend_x11_class_init (MetaBackendX11Class *klass)
|
||||
static void
|
||||
meta_backend_x11_init (MetaBackendX11 *x11)
|
||||
{
|
||||
XInitThreads ();
|
||||
}
|
||||
|
||||
Display *
|
||||
|
||||
@@ -896,12 +896,16 @@ meta_stage_x11_translate_event (MetaStageX11 *stage_x11,
|
||||
g_debug ("Client message for stage, win:0x%x",
|
||||
(unsigned int) xevent->xany.window);
|
||||
|
||||
if (handle_wm_protocols_event (backend_x11, stage_x11, xevent))
|
||||
if (xevent->xclient.message_type == backend_x11->atom_WM_PROTOCOLS)
|
||||
{
|
||||
event->any.type = CLUTTER_DELETE;
|
||||
event->any.stage = stage;
|
||||
res = TRUE;
|
||||
if (handle_wm_protocols_event (backend_x11, stage_x11, xevent))
|
||||
{
|
||||
event->any.type = CLUTTER_DELETE;
|
||||
event->any.stage = stage;
|
||||
res = TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
default:
|
||||
|
||||
@@ -63,7 +63,6 @@
|
||||
#include "clutter/clutter-mutter.h"
|
||||
#include "cogl/cogl-trace.h"
|
||||
#include "compositor/meta-window-actor-x11.h"
|
||||
#include "compositor/meta-window-actor-wayland.h"
|
||||
#include "compositor/meta-window-actor-private.h"
|
||||
#include "compositor/meta-window-group-private.h"
|
||||
#include "core/core.h"
|
||||
@@ -83,6 +82,7 @@
|
||||
#include "x11/meta-x11-display-private.h"
|
||||
|
||||
#ifdef HAVE_WAYLAND
|
||||
#include "compositor/meta-window-actor-wayland.h"
|
||||
#include "wayland/meta-wayland-private.h"
|
||||
#endif
|
||||
|
||||
@@ -607,6 +607,7 @@ meta_compositor_add_window (MetaCompositor *compositor,
|
||||
|
||||
window_actor = g_object_new (window_actor_type,
|
||||
"meta-window", window,
|
||||
"show-on-set-parent", FALSE,
|
||||
NULL);
|
||||
|
||||
if (window->layer == META_LAYER_OVERRIDE_REDIRECT)
|
||||
|
||||
@@ -243,6 +243,8 @@ meta_shaped_texture_dispose (GObject *object)
|
||||
meta_shaped_texture_set_mask_texture (stex, NULL);
|
||||
meta_shaped_texture_reset_pipelines (stex);
|
||||
|
||||
g_clear_pointer (&stex->opaque_region, cairo_region_destroy);
|
||||
|
||||
g_clear_pointer (&stex->snippet, cogl_object_unref);
|
||||
|
||||
G_OBJECT_CLASS (meta_shaped_texture_parent_class)->dispose (object);
|
||||
@@ -458,16 +460,11 @@ set_cogl_texture (MetaShapedTexture *stex,
|
||||
{
|
||||
int width, height;
|
||||
|
||||
g_return_if_fail (META_IS_SHAPED_TEXTURE (stex));
|
||||
|
||||
if (stex->texture)
|
||||
cogl_object_unref (stex->texture);
|
||||
|
||||
stex->texture = cogl_tex;
|
||||
cogl_clear_object (&stex->texture);
|
||||
|
||||
if (cogl_tex != NULL)
|
||||
{
|
||||
cogl_object_ref (cogl_tex);
|
||||
stex->texture = cogl_object_ref (cogl_tex);
|
||||
width = cogl_texture_get_width (COGL_TEXTURE (cogl_tex));
|
||||
height = cogl_texture_get_height (COGL_TEXTURE (cogl_tex));
|
||||
}
|
||||
@@ -937,6 +934,9 @@ meta_shaped_texture_set_texture (MetaShapedTexture *stex,
|
||||
{
|
||||
g_return_if_fail (META_IS_SHAPED_TEXTURE (stex));
|
||||
|
||||
if (stex->texture == texture)
|
||||
return;
|
||||
|
||||
set_cogl_texture (stex, texture);
|
||||
}
|
||||
|
||||
|
||||
@@ -63,6 +63,15 @@
|
||||
#define META_KEY_BINDING_PRIMARY_LAYOUT 0
|
||||
#define META_KEY_BINDING_SECONDARY_LAYOUT 1
|
||||
|
||||
/* Only for special modifier keys */
|
||||
#define IGNORED_MODIFIERS (CLUTTER_LOCK_MASK | \
|
||||
CLUTTER_MOD2_MASK | \
|
||||
CLUTTER_BUTTON1_MASK | \
|
||||
CLUTTER_BUTTON2_MASK | \
|
||||
CLUTTER_BUTTON3_MASK | \
|
||||
CLUTTER_BUTTON4_MASK | \
|
||||
CLUTTER_BUTTON5_MASK)
|
||||
|
||||
static gboolean add_builtin_keybinding (MetaDisplay *display,
|
||||
const char *name,
|
||||
GSettings *settings,
|
||||
@@ -2114,6 +2123,7 @@ process_special_modifier_key (MetaDisplay *display,
|
||||
return TRUE;
|
||||
}
|
||||
else if (event->type == CLUTTER_KEY_PRESS &&
|
||||
((event->modifier_state & ~(IGNORED_MODIFIERS)) & CLUTTER_MODIFIER_MASK) == 0 &&
|
||||
resolved_key_combo_has_keycode (resolved_key_combo,
|
||||
event->hardware_keycode))
|
||||
{
|
||||
|
||||
@@ -32,9 +32,15 @@ static struct {
|
||||
const char *mimetype_glob;
|
||||
ssize_t max_transfer_size;
|
||||
} supported_mimetypes[] = {
|
||||
{ "image/tiff", MAX_IMAGE_SIZE },
|
||||
{ "image/bmp", MAX_IMAGE_SIZE },
|
||||
{ "image/gif", MAX_IMAGE_SIZE },
|
||||
{ "image/jpeg", MAX_IMAGE_SIZE },
|
||||
{ "image/webp", MAX_IMAGE_SIZE },
|
||||
{ "image/png", MAX_IMAGE_SIZE },
|
||||
{ "image/svg+xml", MAX_IMAGE_SIZE },
|
||||
{ "text/plain", MAX_TEXT_SIZE },
|
||||
{ "text/plain;charset=utf-8", MAX_TEXT_SIZE },
|
||||
{ "image/*", MAX_IMAGE_SIZE },
|
||||
};
|
||||
|
||||
static gboolean
|
||||
|
||||
32
src/core/meta-selection-private.h
Normal file
32
src/core/meta-selection-private.h
Normal file
@@ -0,0 +1,32 @@
|
||||
/*
|
||||
* Copyright (C) 2020 Red Hat
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License as
|
||||
* published by the Free Software Foundation; either version 2 of the
|
||||
* License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
|
||||
* 02111-1307, USA.
|
||||
*
|
||||
* Written by:
|
||||
* Carlos Garnacho <carlosg@gnome.org>
|
||||
*/
|
||||
|
||||
#ifndef META_SELECTION_PRIVATE_H
|
||||
#define META_SELECTION_PRIVATE_H
|
||||
|
||||
#include "meta/meta-selection.h"
|
||||
|
||||
MetaSelectionSource *
|
||||
meta_selection_get_current_owner (MetaSelection *selection,
|
||||
MetaSelectionType selection_type);
|
||||
|
||||
#endif /* META_SELECTION_PRIVATE_H */
|
||||
@@ -21,6 +21,7 @@
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include "core/meta-selection-private.h"
|
||||
#include "meta/meta-selection.h"
|
||||
|
||||
typedef struct TransferRequest TransferRequest;
|
||||
@@ -50,6 +51,9 @@ static guint signals[N_SIGNALS] = { 0 };
|
||||
|
||||
G_DEFINE_TYPE (MetaSelection, meta_selection, G_TYPE_OBJECT)
|
||||
|
||||
static void read_selection_source_async (GTask *task,
|
||||
TransferRequest *request);
|
||||
|
||||
static void
|
||||
meta_selection_class_init (MetaSelectionClass *klass)
|
||||
{
|
||||
@@ -198,6 +202,7 @@ write_cb (GOutputStream *stream,
|
||||
GAsyncResult *result,
|
||||
GTask *task)
|
||||
{
|
||||
TransferRequest *request;
|
||||
GError *error = NULL;
|
||||
|
||||
g_output_stream_write_bytes_finish (stream, result, &error);
|
||||
@@ -208,8 +213,17 @@ write_cb (GOutputStream *stream,
|
||||
return;
|
||||
}
|
||||
|
||||
g_task_return_boolean (task, TRUE);
|
||||
g_object_unref (task);
|
||||
request = g_task_get_task_data (task);
|
||||
|
||||
if (request->len > 0)
|
||||
{
|
||||
read_selection_source_async (task, request);
|
||||
}
|
||||
else
|
||||
{
|
||||
g_task_return_boolean (task, TRUE);
|
||||
g_object_unref (task);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
@@ -228,8 +242,26 @@ read_cb (GInputStream *stream,
|
||||
g_object_unref (task);
|
||||
return;
|
||||
}
|
||||
else if (g_bytes_get_size (bytes) == 0)
|
||||
{
|
||||
g_task_return_boolean (task, TRUE);
|
||||
g_object_unref (task);
|
||||
return;
|
||||
}
|
||||
|
||||
request = g_task_get_task_data (task);
|
||||
|
||||
if (request->len < g_bytes_get_size (bytes))
|
||||
{
|
||||
GBytes *copy;
|
||||
|
||||
/* Trim content */
|
||||
copy = g_bytes_new_from_bytes (bytes, 0, request->len);
|
||||
g_bytes_unref (bytes);
|
||||
bytes = copy;
|
||||
}
|
||||
|
||||
request->len -= g_bytes_get_size (bytes);
|
||||
g_output_stream_write_bytes_async (request->ostream,
|
||||
bytes,
|
||||
G_PRIORITY_DEFAULT,
|
||||
@@ -239,6 +271,18 @@ read_cb (GInputStream *stream,
|
||||
g_bytes_unref (bytes);
|
||||
}
|
||||
|
||||
static void
|
||||
read_selection_source_async (GTask *task,
|
||||
TransferRequest *request)
|
||||
{
|
||||
g_input_stream_read_bytes_async (request->istream,
|
||||
(gsize) request->len,
|
||||
G_PRIORITY_DEFAULT,
|
||||
g_task_get_cancellable (task),
|
||||
(GAsyncReadyCallback) read_cb,
|
||||
task);
|
||||
}
|
||||
|
||||
static void
|
||||
source_read_cb (MetaSelectionSource *source,
|
||||
GAsyncResult *result,
|
||||
@@ -271,12 +315,7 @@ source_read_cb (MetaSelectionSource *source,
|
||||
}
|
||||
else
|
||||
{
|
||||
g_input_stream_read_bytes_async (request->istream,
|
||||
(gsize) request->len,
|
||||
G_PRIORITY_DEFAULT,
|
||||
g_task_get_cancellable (task),
|
||||
(GAsyncReadyCallback) read_cb,
|
||||
task);
|
||||
read_selection_source_async (task, request);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -345,3 +384,13 @@ meta_selection_transfer_finish (MetaSelection *selection,
|
||||
|
||||
return g_task_propagate_boolean (G_TASK (result), error);
|
||||
}
|
||||
|
||||
MetaSelectionSource *
|
||||
meta_selection_get_current_owner (MetaSelection *selection,
|
||||
MetaSelectionType selection_type)
|
||||
{
|
||||
g_return_val_if_fail (META_IS_SELECTION (selection), NULL);
|
||||
g_return_val_if_fail (selection_type < META_N_SELECTION_TYPES, NULL);
|
||||
|
||||
return selection->owners[selection_type];
|
||||
}
|
||||
|
||||
@@ -1289,7 +1289,10 @@ _meta_window_shared_new (MetaDisplay *display,
|
||||
window->initial_workspace);
|
||||
}
|
||||
|
||||
set_workspace_state (window, on_all_workspaces, workspace);
|
||||
/* Ignore when a window requests to be placed on a non-existent workspace
|
||||
*/
|
||||
if (on_all_workspaces || workspace != NULL)
|
||||
set_workspace_state (window, on_all_workspaces, workspace);
|
||||
}
|
||||
|
||||
/* override-redirect windows are subtly different from other windows
|
||||
@@ -1308,7 +1311,7 @@ _meta_window_shared_new (MetaDisplay *display,
|
||||
|
||||
g_warn_if_fail (!window->transient_for->override_redirect);
|
||||
set_workspace_state (window,
|
||||
should_be_on_all_workspaces (window->transient_for),
|
||||
window->transient_for->on_all_workspaces,
|
||||
window->transient_for->workspace);
|
||||
}
|
||||
else if (window->on_all_workspaces)
|
||||
|
||||
@@ -28,6 +28,7 @@
|
||||
#include "compositor/meta-surface-actor-wayland.h"
|
||||
#include "compositor/meta-window-actor-wayland.h"
|
||||
#include "compositor/region-utils.h"
|
||||
#include "wayland/meta-wayland-buffer.h"
|
||||
#include "wayland/meta-wayland-surface.h"
|
||||
#include "wayland/meta-window-wayland.h"
|
||||
|
||||
@@ -147,13 +148,33 @@ meta_wayland_actor_surface_real_sync_actor_state (MetaWaylandActorSurface *actor
|
||||
meta_wayland_surface_role_get_surface (surface_role);
|
||||
MetaSurfaceActor *surface_actor;
|
||||
MetaShapedTexture *stex;
|
||||
GNode *n;
|
||||
MetaWaylandBuffer *buffer;
|
||||
cairo_rectangle_int_t surface_rect;
|
||||
int geometry_scale;
|
||||
MetaWaylandSurface *subsurface_surface;
|
||||
|
||||
surface_actor = priv->actor;
|
||||
stex = meta_surface_actor_get_texture (surface_actor);
|
||||
meta_shaped_texture_set_buffer_scale (stex, surface->scale);
|
||||
|
||||
buffer = surface->buffer_ref.buffer;
|
||||
if (buffer)
|
||||
{
|
||||
CoglSnippet *snippet;
|
||||
gboolean is_y_inverted;
|
||||
|
||||
snippet = meta_wayland_buffer_create_snippet (buffer);
|
||||
is_y_inverted = meta_wayland_buffer_is_y_inverted (buffer);
|
||||
|
||||
meta_shaped_texture_set_texture (stex, surface->texture);
|
||||
meta_shaped_texture_set_snippet (stex, snippet);
|
||||
meta_shaped_texture_set_is_y_inverted (stex, is_y_inverted);
|
||||
meta_shaped_texture_set_buffer_scale (stex, surface->scale);
|
||||
cogl_clear_object (&snippet);
|
||||
}
|
||||
else
|
||||
{
|
||||
meta_shaped_texture_set_texture (stex, NULL);
|
||||
}
|
||||
|
||||
/* Wayland surface coordinate space -> stage coordinate space */
|
||||
geometry_scale = meta_wayland_actor_surface_get_geometry_scale (actor_surface);
|
||||
@@ -213,19 +234,12 @@ meta_wayland_actor_surface_real_sync_actor_state (MetaWaylandActorSurface *actor
|
||||
meta_surface_actor_reset_viewport_dst_size (surface_actor);
|
||||
}
|
||||
|
||||
for (n = g_node_first_child (surface->subsurface_branch_node);
|
||||
n;
|
||||
n = g_node_next_sibling (n))
|
||||
META_WAYLAND_SURFACE_FOREACH_SUBSURFACE (surface, subsurface_surface)
|
||||
{
|
||||
MetaWaylandSurface *subsurface_surface = n->data;
|
||||
MetaWaylandActorSurface *subsurface_actor_surface;
|
||||
MetaWaylandActorSurface *actor_surface;
|
||||
|
||||
if (G_NODE_IS_LEAF (n))
|
||||
continue;
|
||||
|
||||
subsurface_actor_surface =
|
||||
META_WAYLAND_ACTOR_SURFACE (subsurface_surface->role);
|
||||
meta_wayland_actor_surface_sync_actor_state (subsurface_actor_surface);
|
||||
actor_surface = META_WAYLAND_ACTOR_SURFACE (subsurface_surface->role);
|
||||
meta_wayland_actor_surface_sync_actor_state (actor_surface);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -278,6 +292,9 @@ meta_wayland_actor_surface_is_on_logical_monitor (MetaWaylandSurfaceRole *surfac
|
||||
MetaRectangle logical_monitor_layout;
|
||||
gboolean is_on_monitor;
|
||||
|
||||
if (!clutter_actor_is_mapped (actor))
|
||||
return FALSE;
|
||||
|
||||
clutter_actor_get_transformed_position (actor, &x, &y);
|
||||
clutter_actor_get_transformed_size (actor, &width, &height);
|
||||
|
||||
@@ -355,6 +372,16 @@ meta_wayland_actor_surface_reset_actor (MetaWaylandActorSurface *actor_surface)
|
||||
meta_wayland_actor_surface_get_instance_private (actor_surface);
|
||||
MetaWaylandSurface *surface =
|
||||
meta_wayland_surface_role_get_surface (META_WAYLAND_SURFACE_ROLE (actor_surface));
|
||||
MetaWaylandSurface *subsurface_surface;
|
||||
|
||||
META_WAYLAND_SURFACE_FOREACH_SUBSURFACE (surface, subsurface_surface)
|
||||
{
|
||||
MetaWaylandActorSurface *actor_surface;
|
||||
|
||||
actor_surface = META_WAYLAND_ACTOR_SURFACE (subsurface_surface->role);
|
||||
meta_wayland_actor_surface_reset_actor (actor_surface);
|
||||
meta_wayland_actor_surface_sync_actor_state (actor_surface);
|
||||
}
|
||||
|
||||
clear_surface_actor (actor_surface);
|
||||
|
||||
|
||||
@@ -198,7 +198,6 @@ shm_buffer_get_cogl_pixel_format (struct wl_shm_buffer *shm_buffer,
|
||||
static gboolean
|
||||
shm_buffer_attach (MetaWaylandBuffer *buffer,
|
||||
CoglTexture **texture,
|
||||
gboolean *changed_texture,
|
||||
GError **error)
|
||||
{
|
||||
MetaBackend *backend = meta_get_backend ();
|
||||
@@ -224,7 +223,6 @@ shm_buffer_attach (MetaWaylandBuffer *buffer,
|
||||
_cogl_texture_get_format (*texture) == format)
|
||||
{
|
||||
buffer->is_y_inverted = TRUE;
|
||||
*changed_texture = FALSE;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
@@ -269,7 +267,6 @@ shm_buffer_attach (MetaWaylandBuffer *buffer,
|
||||
return FALSE;
|
||||
|
||||
*texture = new_texture;
|
||||
*changed_texture = TRUE;
|
||||
buffer->is_y_inverted = TRUE;
|
||||
|
||||
return TRUE;
|
||||
@@ -278,7 +275,6 @@ shm_buffer_attach (MetaWaylandBuffer *buffer,
|
||||
static gboolean
|
||||
egl_image_buffer_attach (MetaWaylandBuffer *buffer,
|
||||
CoglTexture **texture,
|
||||
gboolean *changed_texture,
|
||||
GError **error)
|
||||
{
|
||||
MetaBackend *backend = meta_get_backend ();
|
||||
@@ -294,7 +290,6 @@ egl_image_buffer_attach (MetaWaylandBuffer *buffer,
|
||||
|
||||
if (buffer->egl_image.texture)
|
||||
{
|
||||
*changed_texture = *texture != buffer->egl_image.texture;
|
||||
cogl_clear_object (texture);
|
||||
*texture = cogl_object_ref (buffer->egl_image.texture);
|
||||
return TRUE;
|
||||
@@ -362,7 +357,6 @@ egl_image_buffer_attach (MetaWaylandBuffer *buffer,
|
||||
|
||||
cogl_clear_object (texture);
|
||||
*texture = cogl_object_ref (buffer->egl_image.texture);
|
||||
*changed_texture = TRUE;
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
@@ -371,7 +365,6 @@ egl_image_buffer_attach (MetaWaylandBuffer *buffer,
|
||||
static gboolean
|
||||
egl_stream_buffer_attach (MetaWaylandBuffer *buffer,
|
||||
CoglTexture **texture,
|
||||
gboolean *changed_texture,
|
||||
GError **error)
|
||||
{
|
||||
MetaWaylandEglStream *stream = buffer->egl_stream.stream;
|
||||
@@ -381,7 +374,6 @@ egl_stream_buffer_attach (MetaWaylandBuffer *buffer,
|
||||
if (!meta_wayland_egl_stream_attach (stream, error))
|
||||
return FALSE;
|
||||
|
||||
*changed_texture = *texture != buffer->egl_stream.texture;
|
||||
cogl_clear_object (texture);
|
||||
*texture = cogl_object_ref (buffer->egl_stream.texture);
|
||||
|
||||
@@ -411,7 +403,6 @@ egl_stream_buffer_attach (MetaWaylandBuffer *buffer,
|
||||
gboolean
|
||||
meta_wayland_buffer_attach (MetaWaylandBuffer *buffer,
|
||||
CoglTexture **texture,
|
||||
gboolean *changed_texture,
|
||||
GError **error)
|
||||
{
|
||||
g_return_val_if_fail (buffer->resource, FALSE);
|
||||
@@ -428,17 +419,16 @@ meta_wayland_buffer_attach (MetaWaylandBuffer *buffer,
|
||||
switch (buffer->type)
|
||||
{
|
||||
case META_WAYLAND_BUFFER_TYPE_SHM:
|
||||
return shm_buffer_attach (buffer, texture, changed_texture, error);
|
||||
return shm_buffer_attach (buffer, texture, error);
|
||||
case META_WAYLAND_BUFFER_TYPE_EGL_IMAGE:
|
||||
return egl_image_buffer_attach (buffer, texture, changed_texture, error);
|
||||
return egl_image_buffer_attach (buffer, texture, error);
|
||||
#ifdef HAVE_WAYLAND_EGLSTREAM
|
||||
case META_WAYLAND_BUFFER_TYPE_EGL_STREAM:
|
||||
return egl_stream_buffer_attach (buffer, texture, changed_texture, error);
|
||||
return egl_stream_buffer_attach (buffer, texture, error);
|
||||
#endif
|
||||
case META_WAYLAND_BUFFER_TYPE_DMA_BUF:
|
||||
return meta_wayland_dma_buf_buffer_attach (buffer,
|
||||
texture,
|
||||
changed_texture,
|
||||
error);
|
||||
case META_WAYLAND_BUFFER_TYPE_UNKNOWN:
|
||||
g_assert_not_reached ();
|
||||
@@ -456,7 +446,7 @@ meta_wayland_buffer_create_snippet (MetaWaylandBuffer *buffer)
|
||||
if (!buffer->egl_stream.stream)
|
||||
return NULL;
|
||||
|
||||
return meta_wayland_egl_stream_create_snippet ();
|
||||
return meta_wayland_egl_stream_create_snippet (buffer->egl_stream.stream);
|
||||
#else
|
||||
return NULL;
|
||||
#endif /* HAVE_WAYLAND_EGLSTREAM */
|
||||
|
||||
@@ -82,7 +82,6 @@ gboolean meta_wayland_buffer_is_realized (MetaWaylandBuff
|
||||
gboolean meta_wayland_buffer_realize (MetaWaylandBuffer *buffer);
|
||||
gboolean meta_wayland_buffer_attach (MetaWaylandBuffer *buffer,
|
||||
CoglTexture **texture,
|
||||
gboolean *changed_texture,
|
||||
GError **error);
|
||||
CoglSnippet * meta_wayland_buffer_create_snippet (MetaWaylandBuffer *buffer);
|
||||
gboolean meta_wayland_buffer_is_y_inverted (MetaWaylandBuffer *buffer);
|
||||
|
||||
@@ -25,16 +25,10 @@
|
||||
#ifndef META_WAYLAND_DATA_DEVICE_PRIVATE_H
|
||||
#define META_WAYLAND_DATA_DEVICE_PRIVATE_H
|
||||
|
||||
#define META_TYPE_WAYLAND_DATA_SOURCE_WAYLAND (meta_wayland_data_source_wayland_get_type ())
|
||||
G_DECLARE_FINAL_TYPE (MetaWaylandDataSourceWayland,
|
||||
meta_wayland_data_source_wayland,
|
||||
META, WAYLAND_DATA_SOURCE_WAYLAND,
|
||||
MetaWaylandDataSource);
|
||||
|
||||
#define META_TYPE_WAYLAND_DATA_SOURCE_PRIMARY (meta_wayland_data_source_primary_get_type ())
|
||||
G_DECLARE_FINAL_TYPE (MetaWaylandDataSourcePrimary,
|
||||
meta_wayland_data_source_primary,
|
||||
META, WAYLAND_DATA_SOURCE_PRIMARY,
|
||||
MetaWaylandDataSourceWayland);
|
||||
MetaWaylandDataSource);
|
||||
|
||||
#endif /* META_WAYLAND_DATA_DEVICE_PRIVATE_H */
|
||||
|
||||
@@ -65,6 +65,7 @@ struct _MetaWaylandDataOffer
|
||||
|
||||
typedef struct _MetaWaylandDataSourcePrivate
|
||||
{
|
||||
struct wl_resource *resource;
|
||||
MetaWaylandDataOffer *offer;
|
||||
struct wl_array mime_types;
|
||||
gboolean has_target;
|
||||
@@ -74,35 +75,30 @@ typedef struct _MetaWaylandDataSourcePrivate
|
||||
MetaWaylandSeat *seat;
|
||||
guint actions_set : 1;
|
||||
guint in_ask : 1;
|
||||
guint drop_performed : 1;
|
||||
} MetaWaylandDataSourcePrivate;
|
||||
|
||||
typedef struct _MetaWaylandDataSourceWayland
|
||||
{
|
||||
MetaWaylandDataSource parent;
|
||||
|
||||
struct wl_resource *resource;
|
||||
} MetaWaylandDataSourceWayland;
|
||||
|
||||
typedef struct _MetaWaylandDataSourcePrimary
|
||||
{
|
||||
MetaWaylandDataSourceWayland parent;
|
||||
MetaWaylandDataSource parent;
|
||||
} MetaWaylandDataSourcePrimary;
|
||||
|
||||
G_DEFINE_TYPE_WITH_PRIVATE (MetaWaylandDataSource, meta_wayland_data_source,
|
||||
G_TYPE_OBJECT);
|
||||
G_DEFINE_TYPE (MetaWaylandDataSourceWayland, meta_wayland_data_source_wayland,
|
||||
META_TYPE_WAYLAND_DATA_SOURCE);
|
||||
G_DEFINE_TYPE (MetaWaylandDataSourcePrimary, meta_wayland_data_source_primary,
|
||||
META_TYPE_WAYLAND_DATA_SOURCE_WAYLAND);
|
||||
META_TYPE_WAYLAND_DATA_SOURCE);
|
||||
|
||||
static void unset_selection_source (MetaWaylandDataDevice *data_device,
|
||||
MetaSelectionType selection_type);
|
||||
|
||||
static MetaWaylandDataSource *
|
||||
meta_wayland_data_source_wayland_new (struct wl_resource *resource);
|
||||
meta_wayland_data_source_new (struct wl_resource *resource);
|
||||
static MetaWaylandDataSource *
|
||||
meta_wayland_data_source_primary_new (struct wl_resource *resource);
|
||||
|
||||
static void
|
||||
meta_wayland_source_cancel (MetaWaylandDataSource *source);
|
||||
|
||||
static void
|
||||
drag_grab_data_source_destroyed (gpointer data, GObject *where_the_object_was);
|
||||
|
||||
@@ -110,6 +106,31 @@ static struct wl_resource * create_and_send_clipboard_offer (MetaWaylandDataDevi
|
||||
struct wl_resource *target);
|
||||
static struct wl_resource * create_and_send_primary_offer (MetaWaylandDataDevice *data_device,
|
||||
struct wl_resource *target);
|
||||
static struct wl_resource * meta_wayland_data_source_get_resource (MetaWaylandDataSource *source);
|
||||
|
||||
static void
|
||||
move_resources (struct wl_list *destination,
|
||||
struct wl_list *source)
|
||||
{
|
||||
wl_list_insert_list (destination, source);
|
||||
wl_list_init (source);
|
||||
}
|
||||
|
||||
static void
|
||||
move_resources_for_client (struct wl_list *destination,
|
||||
struct wl_list *source,
|
||||
struct wl_client *client)
|
||||
{
|
||||
struct wl_resource *resource, *tmp;
|
||||
wl_resource_for_each_safe (resource, tmp, source)
|
||||
{
|
||||
if (wl_resource_get_client (resource) == client)
|
||||
{
|
||||
wl_list_remove (wl_resource_get_link (resource));
|
||||
wl_list_insert (destination, wl_resource_get_link (resource));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
unbind_resource (struct wl_resource *resource)
|
||||
@@ -142,6 +163,10 @@ data_offer_choose_action (MetaWaylandDataOffer *offer)
|
||||
MetaWaylandDataSource *source = offer->source;
|
||||
uint32_t actions, user_action, available_actions;
|
||||
|
||||
if (wl_resource_get_version (offer->resource) <
|
||||
WL_DATA_OFFER_ACTION_SINCE_VERSION)
|
||||
return WL_DATA_DEVICE_MANAGER_DND_ACTION_COPY;
|
||||
|
||||
actions = meta_wayland_data_source_get_actions (source);
|
||||
user_action = meta_wayland_data_source_get_user_action (source);
|
||||
|
||||
@@ -189,6 +214,25 @@ data_offer_update_action (MetaWaylandDataOffer *offer)
|
||||
}
|
||||
}
|
||||
|
||||
static struct wl_resource *
|
||||
meta_wayland_data_source_get_resource (MetaWaylandDataSource *source)
|
||||
{
|
||||
MetaWaylandDataSourcePrivate *priv =
|
||||
meta_wayland_data_source_get_instance_private (source);
|
||||
|
||||
return priv->resource;
|
||||
}
|
||||
|
||||
static void
|
||||
meta_wayland_data_source_set_resource (MetaWaylandDataSource *source,
|
||||
struct wl_resource *resource)
|
||||
{
|
||||
MetaWaylandDataSourcePrivate *priv =
|
||||
meta_wayland_data_source_get_instance_private (source);
|
||||
|
||||
priv->resource = resource;
|
||||
}
|
||||
|
||||
static void
|
||||
meta_wayland_data_source_target (MetaWaylandDataSource *source,
|
||||
const char *mime_type)
|
||||
@@ -334,9 +378,9 @@ meta_wayland_data_source_set_actions (MetaWaylandDataSource *source,
|
||||
priv->actions_set = TRUE;
|
||||
}
|
||||
|
||||
static void
|
||||
meta_wayland_data_source_set_user_action (MetaWaylandDataSource *source,
|
||||
enum wl_data_device_manager_dnd_action action)
|
||||
void
|
||||
meta_wayland_data_source_set_user_action (MetaWaylandDataSource *source,
|
||||
uint32_t action)
|
||||
{
|
||||
MetaWaylandDataSourcePrivate *priv =
|
||||
meta_wayland_data_source_get_instance_private (source);
|
||||
@@ -352,6 +396,15 @@ meta_wayland_data_source_set_user_action (MetaWaylandDataSource
|
||||
data_offer_update_action (offer);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
meta_wayland_data_source_get_drop_performed (MetaWaylandDataSource *source)
|
||||
{
|
||||
MetaWaylandDataSourcePrivate *priv =
|
||||
meta_wayland_data_source_get_instance_private (source);
|
||||
|
||||
return priv->drop_performed;
|
||||
}
|
||||
|
||||
static void
|
||||
data_offer_accept (struct wl_client *client,
|
||||
struct wl_resource *resource,
|
||||
@@ -566,12 +619,19 @@ destroy_data_offer (struct wl_resource *resource)
|
||||
|
||||
if (offer == meta_wayland_data_source_get_current_offer (offer->source))
|
||||
{
|
||||
if (seat->data_device.dnd_data_source == offer->source &&
|
||||
wl_resource_get_version (offer->resource) <
|
||||
WL_DATA_OFFER_ACTION_SINCE_VERSION)
|
||||
meta_wayland_data_source_notify_finish (offer->source);
|
||||
if (seat->data_device.dnd_data_source == offer->source)
|
||||
{
|
||||
if (wl_resource_get_version (offer->resource) <
|
||||
WL_DATA_OFFER_ACTION_SINCE_VERSION)
|
||||
meta_wayland_data_source_notify_finish (offer->source);
|
||||
else if (meta_wayland_data_source_get_drop_performed (offer->source))
|
||||
meta_wayland_source_cancel (offer->source);
|
||||
}
|
||||
else
|
||||
meta_wayland_data_source_set_current_offer (offer->source, NULL);
|
||||
{
|
||||
meta_wayland_data_source_set_current_offer (offer->source, NULL);
|
||||
meta_wayland_data_source_set_has_target (offer->source, FALSE);
|
||||
}
|
||||
}
|
||||
|
||||
g_object_remove_weak_pointer (G_OBJECT (offer->source),
|
||||
@@ -654,12 +714,10 @@ data_source_set_actions (struct wl_client *client,
|
||||
MetaWaylandDataSource *source = wl_resource_get_user_data (resource);
|
||||
MetaWaylandDataSourcePrivate *priv =
|
||||
meta_wayland_data_source_get_instance_private (source);
|
||||
MetaWaylandDataSourceWayland *source_wayland =
|
||||
META_WAYLAND_DATA_SOURCE_WAYLAND (source);
|
||||
|
||||
if (priv->actions_set)
|
||||
{
|
||||
wl_resource_post_error (source_wayland->resource,
|
||||
wl_resource_post_error (priv->resource,
|
||||
WL_DATA_SOURCE_ERROR_INVALID_ACTION_MASK,
|
||||
"cannot set actions more than once");
|
||||
return;
|
||||
@@ -667,7 +725,7 @@ data_source_set_actions (struct wl_client *client,
|
||||
|
||||
if (dnd_actions & ~(ALL_ACTIONS))
|
||||
{
|
||||
wl_resource_post_error (source_wayland->resource,
|
||||
wl_resource_post_error (priv->resource,
|
||||
WL_DATA_SOURCE_ERROR_INVALID_ACTION_MASK,
|
||||
"invalid actions mask %x", dnd_actions);
|
||||
return;
|
||||
@@ -675,7 +733,7 @@ data_source_set_actions (struct wl_client *client,
|
||||
|
||||
if (meta_wayland_data_source_get_seat (source))
|
||||
{
|
||||
wl_resource_post_error (source_wayland->resource,
|
||||
wl_resource_post_error (priv->resource,
|
||||
WL_DATA_SOURCE_ERROR_INVALID_ACTION_MASK,
|
||||
"invalid action change after "
|
||||
"wl_data_device.start_drag");
|
||||
@@ -867,6 +925,12 @@ meta_wayland_drag_grab_set_focus (MetaWaylandDragGrab *drag_grab,
|
||||
client = wl_resource_get_client (surface->resource);
|
||||
|
||||
data_device_resource = wl_resource_find_for_client (&seat->data_device.resource_list, client);
|
||||
if (!data_device_resource)
|
||||
{
|
||||
data_device_resource =
|
||||
wl_resource_find_for_client (&seat->data_device.focus_resource_list,
|
||||
client);
|
||||
}
|
||||
|
||||
if (source && data_device_resource)
|
||||
offer = create_and_send_dnd_offer (source, data_device_resource);
|
||||
@@ -1018,7 +1082,7 @@ meta_wayland_data_source_fake_read (MetaWaylandDataSource *source,
|
||||
|
||||
static void
|
||||
drag_grab_button (MetaWaylandPointerGrab *grab,
|
||||
const ClutterEvent *event)
|
||||
const ClutterEvent *event)
|
||||
{
|
||||
MetaWaylandDragGrab *drag_grab = (MetaWaylandDragGrab*) grab;
|
||||
MetaWaylandSeat *seat = drag_grab->seat;
|
||||
@@ -1031,7 +1095,6 @@ drag_grab_button (MetaWaylandPointerGrab *grab,
|
||||
gboolean success;
|
||||
|
||||
if (drag_grab->drag_focus && source &&
|
||||
meta_wayland_data_source_get_current_offer (source) &&
|
||||
meta_wayland_data_source_has_target (source) &&
|
||||
meta_wayland_data_source_get_current_action (source))
|
||||
{
|
||||
@@ -1055,10 +1118,11 @@ drag_grab_button (MetaWaylandPointerGrab *grab,
|
||||
}
|
||||
else
|
||||
{
|
||||
meta_wayland_data_source_set_current_offer (source, NULL);
|
||||
if (source)
|
||||
meta_wayland_data_source_set_current_offer (source, NULL);
|
||||
meta_wayland_data_device_set_dnd_source (&seat->data_device, NULL);
|
||||
unset_selection_source (&seat->data_device, META_SELECTION_DND);
|
||||
success= FALSE;
|
||||
success = FALSE;
|
||||
}
|
||||
|
||||
/* Finish drag and let actor self-destruct */
|
||||
@@ -1297,20 +1361,8 @@ static void
|
||||
selection_data_source_destroyed (gpointer data, GObject *object_was_here)
|
||||
{
|
||||
MetaWaylandDataDevice *data_device = data;
|
||||
MetaWaylandSeat *seat = wl_container_of (data_device, seat, data_device);
|
||||
struct wl_resource *data_device_resource;
|
||||
struct wl_client *focus_client = NULL;
|
||||
|
||||
data_device->selection_data_source = NULL;
|
||||
|
||||
focus_client = meta_wayland_keyboard_get_focus_client (seat->keyboard);
|
||||
if (focus_client)
|
||||
{
|
||||
data_device_resource = wl_resource_find_for_client (&data_device->resource_list, focus_client);
|
||||
if (data_device_resource)
|
||||
wl_data_device_send_selection (data_device_resource, NULL);
|
||||
}
|
||||
|
||||
unset_selection_source (data_device, META_SELECTION_CLIPBOARD);
|
||||
}
|
||||
|
||||
@@ -1319,10 +1371,10 @@ meta_wayland_source_send (MetaWaylandDataSource *source,
|
||||
const gchar *mime_type,
|
||||
gint fd)
|
||||
{
|
||||
MetaWaylandDataSourceWayland *source_wayland =
|
||||
META_WAYLAND_DATA_SOURCE_WAYLAND (source);
|
||||
MetaWaylandDataSourcePrivate *priv =
|
||||
meta_wayland_data_source_get_instance_private (source);
|
||||
|
||||
wl_data_source_send_send (source_wayland->resource, mime_type, fd);
|
||||
wl_data_source_send_send (priv->resource, mime_type, fd);
|
||||
close (fd);
|
||||
}
|
||||
|
||||
@@ -1330,43 +1382,48 @@ static void
|
||||
meta_wayland_source_target (MetaWaylandDataSource *source,
|
||||
const gchar *mime_type)
|
||||
{
|
||||
MetaWaylandDataSourceWayland *source_wayland =
|
||||
META_WAYLAND_DATA_SOURCE_WAYLAND (source);
|
||||
MetaWaylandDataSourcePrivate *priv =
|
||||
meta_wayland_data_source_get_instance_private (source);
|
||||
|
||||
wl_data_source_send_target (source_wayland->resource, mime_type);
|
||||
wl_data_source_send_target (priv->resource, mime_type);
|
||||
}
|
||||
|
||||
static void
|
||||
meta_wayland_source_cancel (MetaWaylandDataSource *source)
|
||||
{
|
||||
MetaWaylandDataSourceWayland *source_wayland =
|
||||
META_WAYLAND_DATA_SOURCE_WAYLAND (source);
|
||||
MetaWaylandDataSourcePrivate *priv =
|
||||
meta_wayland_data_source_get_instance_private (source);
|
||||
|
||||
if (source_wayland->resource)
|
||||
wl_data_source_send_cancelled (source_wayland->resource);
|
||||
if (!priv->resource)
|
||||
return;
|
||||
|
||||
wl_data_source_send_cancelled (priv->resource);
|
||||
}
|
||||
|
||||
static void
|
||||
meta_wayland_source_action (MetaWaylandDataSource *source,
|
||||
enum wl_data_device_manager_dnd_action action)
|
||||
{
|
||||
MetaWaylandDataSourceWayland *source_wayland =
|
||||
META_WAYLAND_DATA_SOURCE_WAYLAND (source);
|
||||
MetaWaylandDataSourcePrivate *priv =
|
||||
meta_wayland_data_source_get_instance_private (source);
|
||||
|
||||
if (wl_resource_get_version (source_wayland->resource) >=
|
||||
if (wl_resource_get_version (priv->resource) >=
|
||||
WL_DATA_SOURCE_ACTION_SINCE_VERSION)
|
||||
wl_data_source_send_action (source_wayland->resource, action);
|
||||
wl_data_source_send_action (priv->resource, action);
|
||||
}
|
||||
|
||||
static void
|
||||
meta_wayland_source_drop_performed (MetaWaylandDataSource *source)
|
||||
{
|
||||
MetaWaylandDataSourceWayland *source_wayland =
|
||||
META_WAYLAND_DATA_SOURCE_WAYLAND (source);
|
||||
MetaWaylandDataSourcePrivate *priv =
|
||||
meta_wayland_data_source_get_instance_private (source);
|
||||
|
||||
if (wl_resource_get_version (source_wayland->resource) >=
|
||||
if (wl_resource_get_version (priv->resource) >=
|
||||
WL_DATA_SOURCE_DND_DROP_PERFORMED_SINCE_VERSION)
|
||||
wl_data_source_send_dnd_drop_performed (source_wayland->resource);
|
||||
{
|
||||
priv->drop_performed = TRUE;
|
||||
wl_data_source_send_dnd_drop_performed (priv->resource);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
@@ -1374,8 +1431,8 @@ meta_wayland_source_drag_finished (MetaWaylandDataSource *source)
|
||||
{
|
||||
MetaWaylandCompositor *compositor = meta_wayland_compositor_get_default ();
|
||||
MetaWaylandDataDevice *data_device = &compositor->seat->data_device;
|
||||
MetaWaylandDataSourceWayland *source_wayland =
|
||||
META_WAYLAND_DATA_SOURCE_WAYLAND (source);
|
||||
MetaWaylandDataSourcePrivate *priv =
|
||||
meta_wayland_data_source_get_instance_private (source);
|
||||
enum wl_data_device_manager_dnd_action action;
|
||||
|
||||
if (meta_wayland_source_get_in_ask (source))
|
||||
@@ -1384,81 +1441,15 @@ meta_wayland_source_drag_finished (MetaWaylandDataSource *source)
|
||||
meta_wayland_source_action (source, action);
|
||||
}
|
||||
|
||||
if (wl_resource_get_version (source_wayland->resource) >=
|
||||
if (wl_resource_get_version (priv->resource) >=
|
||||
WL_DATA_SOURCE_DND_FINISHED_SINCE_VERSION)
|
||||
wl_data_source_send_dnd_finished (source_wayland->resource);
|
||||
wl_data_source_send_dnd_finished (priv->resource);
|
||||
|
||||
unset_selection_source (data_device, META_SELECTION_DND);
|
||||
}
|
||||
|
||||
static void
|
||||
meta_wayland_source_finalize (GObject *object)
|
||||
{
|
||||
G_OBJECT_CLASS (meta_wayland_data_source_wayland_parent_class)->finalize (object);
|
||||
}
|
||||
|
||||
static void
|
||||
meta_wayland_data_source_wayland_init (MetaWaylandDataSourceWayland *source_wayland)
|
||||
{
|
||||
}
|
||||
|
||||
static void
|
||||
meta_wayland_data_source_wayland_class_init (MetaWaylandDataSourceWaylandClass *klass)
|
||||
{
|
||||
GObjectClass *object_class = G_OBJECT_CLASS (klass);
|
||||
MetaWaylandDataSourceClass *data_source_class =
|
||||
META_WAYLAND_DATA_SOURCE_CLASS (klass);
|
||||
|
||||
object_class->finalize = meta_wayland_source_finalize;
|
||||
|
||||
data_source_class->send = meta_wayland_source_send;
|
||||
data_source_class->target = meta_wayland_source_target;
|
||||
data_source_class->cancel = meta_wayland_source_cancel;
|
||||
data_source_class->action = meta_wayland_source_action;
|
||||
data_source_class->drop_performed = meta_wayland_source_drop_performed;
|
||||
data_source_class->drag_finished = meta_wayland_source_drag_finished;
|
||||
}
|
||||
|
||||
static void
|
||||
meta_wayland_data_source_primary_send (MetaWaylandDataSource *source,
|
||||
const gchar *mime_type,
|
||||
gint fd)
|
||||
{
|
||||
MetaWaylandDataSourceWayland *source_wayland;
|
||||
|
||||
source_wayland = META_WAYLAND_DATA_SOURCE_WAYLAND (source);
|
||||
gtk_primary_selection_source_send_send (source_wayland->resource,
|
||||
mime_type, fd);
|
||||
close (fd);
|
||||
}
|
||||
|
||||
static void
|
||||
meta_wayland_data_source_primary_cancel (MetaWaylandDataSource *source)
|
||||
{
|
||||
MetaWaylandDataSourceWayland *source_wayland;
|
||||
|
||||
source_wayland = META_WAYLAND_DATA_SOURCE_WAYLAND (source);
|
||||
if (source_wayland->resource)
|
||||
gtk_primary_selection_source_send_cancelled (source_wayland->resource);
|
||||
}
|
||||
|
||||
static void
|
||||
meta_wayland_data_source_primary_init (MetaWaylandDataSourcePrimary *source_primary)
|
||||
{
|
||||
}
|
||||
|
||||
static void
|
||||
meta_wayland_data_source_primary_class_init (MetaWaylandDataSourcePrimaryClass *klass)
|
||||
{
|
||||
MetaWaylandDataSourceClass *data_source_class =
|
||||
META_WAYLAND_DATA_SOURCE_CLASS (klass);
|
||||
|
||||
data_source_class->send = meta_wayland_data_source_primary_send;
|
||||
data_source_class->cancel = meta_wayland_data_source_primary_cancel;
|
||||
}
|
||||
|
||||
static void
|
||||
meta_wayland_data_source_finalize (GObject *object)
|
||||
{
|
||||
MetaWaylandDataSource *source = META_WAYLAND_DATA_SOURCE (object);
|
||||
MetaWaylandDataSourcePrivate *priv =
|
||||
@@ -1480,6 +1471,7 @@ meta_wayland_data_source_init (MetaWaylandDataSource *source)
|
||||
|
||||
wl_array_init (&priv->mime_types);
|
||||
priv->current_dnd_action = -1;
|
||||
priv->drop_performed = FALSE;
|
||||
}
|
||||
|
||||
static void
|
||||
@@ -1487,7 +1479,49 @@ meta_wayland_data_source_class_init (MetaWaylandDataSourceClass *klass)
|
||||
{
|
||||
GObjectClass *object_class = G_OBJECT_CLASS (klass);
|
||||
|
||||
object_class->finalize = meta_wayland_data_source_finalize;
|
||||
object_class->finalize = meta_wayland_source_finalize;
|
||||
|
||||
klass->send = meta_wayland_source_send;
|
||||
klass->target = meta_wayland_source_target;
|
||||
klass->cancel = meta_wayland_source_cancel;
|
||||
klass->action = meta_wayland_source_action;
|
||||
klass->drop_performed = meta_wayland_source_drop_performed;
|
||||
klass->drag_finished = meta_wayland_source_drag_finished;
|
||||
}
|
||||
|
||||
static void
|
||||
meta_wayland_data_source_primary_send (MetaWaylandDataSource *source,
|
||||
const gchar *mime_type,
|
||||
gint fd)
|
||||
{
|
||||
struct wl_resource *resource = meta_wayland_data_source_get_resource (source);
|
||||
|
||||
gtk_primary_selection_source_send_send (resource, mime_type, fd);
|
||||
close (fd);
|
||||
}
|
||||
|
||||
static void
|
||||
meta_wayland_data_source_primary_cancel (MetaWaylandDataSource *source)
|
||||
{
|
||||
struct wl_resource *resource = meta_wayland_data_source_get_resource (source);
|
||||
|
||||
if (resource)
|
||||
gtk_primary_selection_source_send_cancelled (resource);
|
||||
}
|
||||
|
||||
static void
|
||||
meta_wayland_data_source_primary_init (MetaWaylandDataSourcePrimary *source_primary)
|
||||
{
|
||||
}
|
||||
|
||||
static void
|
||||
meta_wayland_data_source_primary_class_init (MetaWaylandDataSourcePrimaryClass *klass)
|
||||
{
|
||||
MetaWaylandDataSourceClass *data_source_class =
|
||||
META_WAYLAND_DATA_SOURCE_CLASS (klass);
|
||||
|
||||
data_source_class->send = meta_wayland_data_source_primary_send;
|
||||
data_source_class->cancel = meta_wayland_data_source_primary_cancel;
|
||||
}
|
||||
|
||||
static void
|
||||
@@ -1630,8 +1664,6 @@ meta_wayland_data_device_set_selection (MetaWaylandDataDevice *data_device,
|
||||
guint32 serial)
|
||||
{
|
||||
MetaWaylandSeat *seat = wl_container_of (data_device, seat, data_device);
|
||||
struct wl_resource *data_device_resource;
|
||||
struct wl_client *focus_client;
|
||||
MetaSelectionSource *selection_source;
|
||||
|
||||
if (data_device->selection_data_source &&
|
||||
@@ -1640,7 +1672,6 @@ meta_wayland_data_device_set_selection (MetaWaylandDataDevice *data_device,
|
||||
|
||||
if (data_device->selection_data_source)
|
||||
{
|
||||
meta_wayland_data_source_cancel (data_device->selection_data_source);
|
||||
g_object_weak_unref (G_OBJECT (data_device->selection_data_source),
|
||||
selection_data_source_destroyed,
|
||||
data_device);
|
||||
@@ -1667,18 +1698,6 @@ meta_wayland_data_device_set_selection (MetaWaylandDataDevice *data_device,
|
||||
set_selection_source (data_device, META_SELECTION_CLIPBOARD,
|
||||
selection_source);
|
||||
g_object_unref (selection_source);
|
||||
|
||||
focus_client = meta_wayland_keyboard_get_focus_client (seat->keyboard);
|
||||
if (focus_client)
|
||||
{
|
||||
data_device_resource = wl_resource_find_for_client (&data_device->resource_list, focus_client);
|
||||
if (data_device_resource)
|
||||
{
|
||||
struct wl_resource *offer;
|
||||
offer = create_and_send_clipboard_offer (data_device, data_device_resource);
|
||||
wl_data_device_send_selection (data_device_resource, offer);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
@@ -1688,6 +1707,7 @@ data_device_set_selection (struct wl_client *client,
|
||||
guint32 serial)
|
||||
{
|
||||
MetaWaylandDataDevice *data_device = wl_resource_get_user_data (resource);
|
||||
MetaWaylandSeat *seat = wl_container_of (data_device, seat, data_device);
|
||||
MetaWaylandDataSourcePrivate *priv;
|
||||
MetaWaylandDataSource *source;
|
||||
|
||||
@@ -1709,6 +1729,10 @@ data_device_set_selection (struct wl_client *client,
|
||||
}
|
||||
}
|
||||
|
||||
if (wl_resource_get_client (resource) !=
|
||||
meta_wayland_keyboard_get_focus_client (seat->keyboard))
|
||||
return;
|
||||
|
||||
/* FIXME: Store serial and check against incoming serial here. */
|
||||
meta_wayland_data_device_set_selection (data_device, source, serial);
|
||||
}
|
||||
@@ -1724,21 +1748,8 @@ primary_source_destroyed (gpointer data,
|
||||
GObject *object_was_here)
|
||||
{
|
||||
MetaWaylandDataDevice *data_device = data;
|
||||
MetaWaylandSeat *seat = wl_container_of (data_device, seat, data_device);
|
||||
struct wl_client *focus_client = NULL;
|
||||
|
||||
data_device->primary_data_source = NULL;
|
||||
|
||||
focus_client = meta_wayland_keyboard_get_focus_client (seat->keyboard);
|
||||
if (focus_client)
|
||||
{
|
||||
struct wl_resource *data_device_resource;
|
||||
|
||||
data_device_resource = wl_resource_find_for_client (&data_device->primary_resource_list, focus_client);
|
||||
if (data_device_resource)
|
||||
gtk_primary_selection_device_send_selection (data_device_resource, NULL);
|
||||
}
|
||||
|
||||
unset_selection_source (data_device, META_SELECTION_PRIMARY);
|
||||
}
|
||||
|
||||
@@ -1748,20 +1759,9 @@ meta_wayland_data_device_set_primary (MetaWaylandDataDevice *data_device,
|
||||
guint32 serial)
|
||||
{
|
||||
MetaWaylandSeat *seat = wl_container_of (data_device, seat, data_device);
|
||||
struct wl_resource *data_device_resource;
|
||||
struct wl_client *focus_client;
|
||||
MetaSelectionSource *selection_source;
|
||||
|
||||
if (META_IS_WAYLAND_DATA_SOURCE_PRIMARY (source))
|
||||
{
|
||||
struct wl_resource *resource;
|
||||
|
||||
resource = META_WAYLAND_DATA_SOURCE_WAYLAND (source)->resource;
|
||||
|
||||
if (wl_resource_get_client (resource) !=
|
||||
meta_wayland_keyboard_get_focus_client (seat->keyboard))
|
||||
return;
|
||||
}
|
||||
g_assert (!source || META_IS_WAYLAND_DATA_SOURCE_PRIMARY (source));
|
||||
|
||||
if (data_device->primary_data_source &&
|
||||
data_device->primary_serial - serial < UINT32_MAX / 2)
|
||||
@@ -1769,7 +1769,6 @@ meta_wayland_data_device_set_primary (MetaWaylandDataDevice *data_device,
|
||||
|
||||
if (data_device->primary_data_source)
|
||||
{
|
||||
meta_wayland_data_source_cancel (data_device->primary_data_source);
|
||||
g_object_weak_unref (G_OBJECT (data_device->primary_data_source),
|
||||
primary_source_destroyed,
|
||||
data_device);
|
||||
@@ -1795,18 +1794,6 @@ meta_wayland_data_device_set_primary (MetaWaylandDataDevice *data_device,
|
||||
set_selection_source (data_device, META_SELECTION_PRIMARY,
|
||||
selection_source);
|
||||
g_object_unref (selection_source);
|
||||
|
||||
focus_client = meta_wayland_keyboard_get_focus_client (seat->keyboard);
|
||||
if (focus_client)
|
||||
{
|
||||
data_device_resource = wl_resource_find_for_client (&data_device->primary_resource_list, focus_client);
|
||||
if (data_device_resource)
|
||||
{
|
||||
struct wl_resource *offer;
|
||||
offer = create_and_send_primary_offer (data_device, data_device_resource);
|
||||
gtk_primary_selection_device_send_selection (data_device_resource, offer);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
@@ -1816,10 +1803,16 @@ primary_device_set_selection (struct wl_client *client,
|
||||
uint32_t serial)
|
||||
{
|
||||
MetaWaylandDataDevice *data_device = wl_resource_get_user_data (resource);
|
||||
MetaWaylandSeat *seat = wl_container_of (data_device, seat, data_device);
|
||||
MetaWaylandDataSource *source = NULL;
|
||||
|
||||
if (source_resource)
|
||||
source = wl_resource_get_user_data (source_resource);
|
||||
|
||||
if (wl_resource_get_client (resource) !=
|
||||
meta_wayland_keyboard_get_focus_client (seat->keyboard))
|
||||
return;
|
||||
|
||||
meta_wayland_data_device_set_primary (data_device, source, serial);
|
||||
}
|
||||
|
||||
@@ -1831,9 +1824,9 @@ static const struct gtk_primary_selection_device_interface primary_device_interf
|
||||
static void
|
||||
destroy_data_source (struct wl_resource *resource)
|
||||
{
|
||||
MetaWaylandDataSourceWayland *source = wl_resource_get_user_data (resource);
|
||||
MetaWaylandDataSource *source = wl_resource_get_user_data (resource);
|
||||
|
||||
source->resource = NULL;
|
||||
meta_wayland_data_source_set_resource (source, NULL);
|
||||
g_object_unref (source);
|
||||
}
|
||||
|
||||
@@ -1845,7 +1838,7 @@ create_data_source (struct wl_client *client,
|
||||
|
||||
source_resource = wl_resource_create (client, &wl_data_source_interface,
|
||||
wl_resource_get_version (resource), id);
|
||||
meta_wayland_data_source_wayland_new (source_resource);
|
||||
meta_wayland_data_source_new (source_resource);
|
||||
}
|
||||
|
||||
static void
|
||||
@@ -1865,10 +1858,7 @@ owner_changed_cb (MetaSelection *selection,
|
||||
|
||||
if (selection_type == META_SELECTION_PRIMARY)
|
||||
{
|
||||
data_device_resource =
|
||||
wl_resource_find_for_client (&data_device->primary_resource_list,
|
||||
focus_client);
|
||||
if (data_device_resource)
|
||||
wl_resource_for_each (data_device_resource, &data_device->primary_focus_resource_list)
|
||||
{
|
||||
struct wl_resource *offer = NULL;
|
||||
|
||||
@@ -1884,10 +1874,7 @@ owner_changed_cb (MetaSelection *selection,
|
||||
}
|
||||
else if (selection_type == META_SELECTION_CLIPBOARD)
|
||||
{
|
||||
data_device_resource =
|
||||
wl_resource_find_for_client (&data_device->resource_list, focus_client);
|
||||
|
||||
if (data_device_resource)
|
||||
wl_resource_for_each (data_device_resource, &data_device->focus_resource_list)
|
||||
{
|
||||
struct wl_resource *offer = NULL;
|
||||
|
||||
@@ -1937,9 +1924,9 @@ static const struct wl_data_device_manager_interface manager_interface = {
|
||||
static void
|
||||
destroy_primary_source (struct wl_resource *resource)
|
||||
{
|
||||
MetaWaylandDataSourceWayland *source = wl_resource_get_user_data (resource);
|
||||
MetaWaylandDataSource *source = wl_resource_get_user_data (resource);
|
||||
|
||||
source->resource = NULL;
|
||||
meta_wayland_data_source_set_resource (source, NULL);
|
||||
g_object_unref (source);
|
||||
}
|
||||
|
||||
@@ -2022,7 +2009,9 @@ void
|
||||
meta_wayland_data_device_init (MetaWaylandDataDevice *data_device)
|
||||
{
|
||||
wl_list_init (&data_device->resource_list);
|
||||
wl_list_init (&data_device->focus_resource_list);
|
||||
wl_list_init (&data_device->primary_resource_list);
|
||||
wl_list_init (&data_device->primary_focus_resource_list);
|
||||
}
|
||||
|
||||
static struct wl_resource *
|
||||
@@ -2104,22 +2093,34 @@ meta_wayland_data_device_set_keyboard_focus (MetaWaylandDataDevice *data_device)
|
||||
return;
|
||||
|
||||
data_device->focus_client = focus_client;
|
||||
move_resources (&data_device->resource_list,
|
||||
&data_device->focus_resource_list);
|
||||
move_resources (&data_device->primary_resource_list,
|
||||
&data_device->primary_focus_resource_list);
|
||||
|
||||
if (!focus_client)
|
||||
return;
|
||||
|
||||
data_device_resource = wl_resource_find_for_client (&data_device->resource_list, focus_client);
|
||||
if (data_device_resource)
|
||||
move_resources_for_client (&data_device->focus_resource_list,
|
||||
&data_device->resource_list,
|
||||
focus_client);
|
||||
|
||||
wl_resource_for_each (data_device_resource, &data_device->focus_resource_list)
|
||||
{
|
||||
struct wl_resource *offer;
|
||||
|
||||
offer = create_and_send_clipboard_offer (data_device, data_device_resource);
|
||||
wl_data_device_send_selection (data_device_resource, offer);
|
||||
}
|
||||
|
||||
data_device_resource = wl_resource_find_for_client (&data_device->primary_resource_list, focus_client);
|
||||
if (data_device_resource)
|
||||
move_resources_for_client (&data_device->primary_focus_resource_list,
|
||||
&data_device->primary_resource_list,
|
||||
focus_client);
|
||||
|
||||
wl_resource_for_each (data_device_resource, &data_device->primary_focus_resource_list)
|
||||
{
|
||||
struct wl_resource *offer;
|
||||
|
||||
offer = create_and_send_primary_offer (data_device, data_device_resource);
|
||||
gtk_primary_selection_device_send_selection (data_device_resource, offer);
|
||||
}
|
||||
@@ -2157,29 +2158,37 @@ meta_wayland_data_source_has_mime_type (const MetaWaylandDataSource *source,
|
||||
}
|
||||
|
||||
static MetaWaylandDataSource *
|
||||
meta_wayland_data_source_wayland_new (struct wl_resource *resource)
|
||||
meta_wayland_data_source_new (struct wl_resource *resource)
|
||||
{
|
||||
MetaWaylandDataSourceWayland *source_wayland =
|
||||
g_object_new (META_TYPE_WAYLAND_DATA_SOURCE_WAYLAND, NULL);
|
||||
MetaWaylandDataSource *source =
|
||||
g_object_new (META_TYPE_WAYLAND_DATA_SOURCE, NULL);
|
||||
MetaWaylandDataSourcePrivate *priv =
|
||||
meta_wayland_data_source_get_instance_private (source);
|
||||
|
||||
source_wayland->resource = resource;
|
||||
meta_wayland_data_source_set_resource (source, resource);
|
||||
wl_resource_set_implementation (resource, &data_source_interface,
|
||||
source_wayland, destroy_data_source);
|
||||
source, destroy_data_source);
|
||||
|
||||
return META_WAYLAND_DATA_SOURCE (source_wayland);
|
||||
if (wl_resource_get_version (resource) < WL_DATA_SOURCE_ACTION_SINCE_VERSION)
|
||||
{
|
||||
priv->dnd_actions = priv->user_dnd_action =
|
||||
WL_DATA_DEVICE_MANAGER_DND_ACTION_COPY;
|
||||
}
|
||||
|
||||
return source;
|
||||
}
|
||||
|
||||
static MetaWaylandDataSource *
|
||||
meta_wayland_data_source_primary_new (struct wl_resource *resource)
|
||||
{
|
||||
MetaWaylandDataSourceWayland *source_primary =
|
||||
MetaWaylandDataSource *source_primary =
|
||||
g_object_new (META_TYPE_WAYLAND_DATA_SOURCE_PRIMARY, NULL);
|
||||
|
||||
source_primary->resource = resource;
|
||||
meta_wayland_data_source_set_resource (source_primary, resource);
|
||||
wl_resource_set_implementation (resource, &primary_source_interface,
|
||||
source_primary, destroy_primary_source);
|
||||
|
||||
return META_WAYLAND_DATA_SOURCE (source_primary);
|
||||
return source_primary;
|
||||
}
|
||||
|
||||
gboolean
|
||||
|
||||
@@ -63,7 +63,9 @@ struct _MetaWaylandDataDevice
|
||||
MetaWaylandDataSource *primary_data_source;
|
||||
struct wl_listener selection_data_source_listener;
|
||||
struct wl_list resource_list;
|
||||
struct wl_list focus_resource_list;
|
||||
struct wl_list primary_resource_list;
|
||||
struct wl_list primary_focus_resource_list;
|
||||
MetaWaylandDragGrab *current_grab;
|
||||
struct wl_client *focus_client;
|
||||
|
||||
@@ -121,6 +123,8 @@ uint32_t meta_wayland_data_source_get_current_action (MetaWaylandDataSource *sou
|
||||
|
||||
void meta_wayland_data_source_set_actions (MetaWaylandDataSource *source,
|
||||
uint32_t dnd_actions);
|
||||
void meta_wayland_data_source_set_user_action (MetaWaylandDataSource *source,
|
||||
uint32_t action);
|
||||
void meta_wayland_data_source_set_current_action (MetaWaylandDataSource *source,
|
||||
uint32_t action);
|
||||
|
||||
|
||||
@@ -158,13 +158,11 @@ meta_wayland_dma_buf_realize_texture (MetaWaylandBuffer *buffer,
|
||||
gboolean
|
||||
meta_wayland_dma_buf_buffer_attach (MetaWaylandBuffer *buffer,
|
||||
CoglTexture **texture,
|
||||
gboolean *changed_texture,
|
||||
GError **error)
|
||||
{
|
||||
if (!meta_wayland_dma_buf_realize_texture (buffer, error))
|
||||
return FALSE;
|
||||
|
||||
*changed_texture = *texture != buffer->dma_buf.texture;
|
||||
cogl_clear_object (texture);
|
||||
*texture = cogl_object_ref (buffer->dma_buf.texture);
|
||||
return TRUE;
|
||||
|
||||
@@ -44,7 +44,6 @@ gboolean meta_wayland_dma_buf_init (MetaWaylandCompositor *compositor);
|
||||
gboolean
|
||||
meta_wayland_dma_buf_buffer_attach (MetaWaylandBuffer *buffer,
|
||||
CoglTexture **texture,
|
||||
gboolean *changed_texture,
|
||||
GError **error);
|
||||
|
||||
MetaWaylandDmaBufBuffer *
|
||||
|
||||
@@ -134,6 +134,7 @@ struct _MetaWaylandEglStream
|
||||
MetaWaylandBuffer *buffer;
|
||||
CoglTexture2D *texture;
|
||||
gboolean is_y_inverted;
|
||||
CoglSnippet *snippet;
|
||||
};
|
||||
|
||||
G_DEFINE_TYPE (MetaWaylandEglStream, meta_wayland_egl_stream,
|
||||
@@ -289,18 +290,22 @@ meta_wayland_egl_stream_is_y_inverted (MetaWaylandEglStream *stream)
|
||||
}
|
||||
|
||||
CoglSnippet *
|
||||
meta_wayland_egl_stream_create_snippet (void)
|
||||
meta_wayland_egl_stream_create_snippet (MetaWaylandEglStream *stream)
|
||||
{
|
||||
CoglSnippet *snippet;
|
||||
if (!stream->snippet)
|
||||
{
|
||||
CoglSnippet *snippet;
|
||||
|
||||
snippet = cogl_snippet_new (COGL_SNIPPET_HOOK_TEXTURE_LOOKUP,
|
||||
"uniform samplerExternalOES tex_external;",
|
||||
NULL);
|
||||
cogl_snippet_set_replace (snippet,
|
||||
"cogl_texel = texture2D (tex_external,\n"
|
||||
" cogl_tex_coord.xy);");
|
||||
snippet = cogl_snippet_new (COGL_SNIPPET_HOOK_TEXTURE_LOOKUP,
|
||||
"uniform samplerExternalOES tex_external;",
|
||||
NULL);
|
||||
cogl_snippet_set_replace (snippet,
|
||||
"cogl_texel = texture2D (tex_external,\n"
|
||||
" cogl_tex_coord.xy);");
|
||||
stream->snippet = snippet;
|
||||
}
|
||||
|
||||
return snippet;
|
||||
return cogl_object_ref (stream->snippet);
|
||||
}
|
||||
|
||||
gboolean
|
||||
@@ -341,6 +346,8 @@ meta_wayland_egl_stream_finalize (GObject *object)
|
||||
|
||||
meta_egl_destroy_stream (egl, egl_display, stream->egl_stream, NULL);
|
||||
|
||||
cogl_clear_object (&stream->snippet);
|
||||
|
||||
G_OBJECT_CLASS (meta_wayland_egl_stream_parent_class)->finalize (object);
|
||||
}
|
||||
|
||||
|
||||
@@ -47,7 +47,7 @@ gboolean meta_wayland_egl_stream_attach (MetaWaylandEglStream *stream,
|
||||
|
||||
CoglTexture2D * meta_wayland_egl_stream_create_texture (MetaWaylandEglStream *stream,
|
||||
GError **error);
|
||||
CoglSnippet * meta_wayland_egl_stream_create_snippet (void);
|
||||
CoglSnippet * meta_wayland_egl_stream_create_snippet (MetaWaylandEglStream *stream);
|
||||
|
||||
gboolean meta_wayland_egl_stream_is_y_inverted (MetaWaylandEglStream *stream);
|
||||
|
||||
|
||||
@@ -599,7 +599,6 @@ meta_wayland_keyboard_disable (MetaWaylandKeyboard *keyboard)
|
||||
|
||||
meta_wayland_keyboard_end_grab (keyboard);
|
||||
meta_wayland_keyboard_set_focus (keyboard, NULL);
|
||||
meta_wayland_xkb_info_destroy (&keyboard->xkb_info);
|
||||
|
||||
wl_list_remove (&keyboard->resource_list);
|
||||
wl_list_init (&keyboard->resource_list);
|
||||
@@ -913,7 +912,18 @@ meta_wayland_keyboard_init (MetaWaylandKeyboard *keyboard)
|
||||
keyboard_handle_focus_surface_destroy;
|
||||
}
|
||||
|
||||
static void
|
||||
meta_wayland_keyboard_finalize (GObject *object)
|
||||
{
|
||||
MetaWaylandKeyboard *keyboard = META_WAYLAND_KEYBOARD (object);
|
||||
|
||||
meta_wayland_xkb_info_destroy (&keyboard->xkb_info);
|
||||
}
|
||||
|
||||
static void
|
||||
meta_wayland_keyboard_class_init (MetaWaylandKeyboardClass *klass)
|
||||
{
|
||||
GObjectClass *object_class = G_OBJECT_CLASS (klass);
|
||||
|
||||
object_class->finalize = meta_wayland_keyboard_finalize;
|
||||
}
|
||||
|
||||
@@ -434,7 +434,7 @@ zxdg_toplevel_v6_set_fullscreen (struct wl_client *client,
|
||||
if (output_resource)
|
||||
{
|
||||
MetaWaylandOutput *output = wl_resource_get_user_data (output_resource);
|
||||
if (output)
|
||||
if (output && output->logical_monitor)
|
||||
meta_window_move_to_monitor (window, output->logical_monitor->number);
|
||||
}
|
||||
|
||||
|
||||
@@ -1209,20 +1209,13 @@ static gboolean
|
||||
pointer_can_grab_surface (MetaWaylandPointer *pointer,
|
||||
MetaWaylandSurface *surface)
|
||||
{
|
||||
GNode *n;
|
||||
MetaWaylandSurface *subsurface;
|
||||
|
||||
if (pointer->focus_surface == surface)
|
||||
return TRUE;
|
||||
|
||||
for (n = g_node_first_child (surface->subsurface_branch_node);
|
||||
n;
|
||||
n = g_node_next_sibling (n))
|
||||
META_WAYLAND_SURFACE_FOREACH_SUBSURFACE (surface, subsurface)
|
||||
{
|
||||
MetaWaylandSurface *subsurface = n->data;
|
||||
|
||||
if (G_NODE_IS_LEAF (n))
|
||||
continue;
|
||||
|
||||
if (pointer_can_grab_surface (pointer, subsurface))
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
@@ -43,23 +43,17 @@ meta_wayland_shell_surface_calculate_geometry (MetaWaylandShellSurface *shell_su
|
||||
MetaWaylandSurface *surface =
|
||||
meta_wayland_surface_role_get_surface (surface_role);
|
||||
MetaRectangle geometry;
|
||||
GNode *n;
|
||||
MetaWaylandSurface *subsurface_surface;
|
||||
|
||||
geometry = (MetaRectangle) {
|
||||
.width = meta_wayland_surface_get_width (surface),
|
||||
.height = meta_wayland_surface_get_height (surface),
|
||||
};
|
||||
|
||||
for (n = g_node_first_child (surface->subsurface_branch_node);
|
||||
n;
|
||||
n = g_node_next_sibling (n))
|
||||
META_WAYLAND_SURFACE_FOREACH_SUBSURFACE (surface, subsurface_surface)
|
||||
{
|
||||
MetaWaylandSurface *subsurface_surface = n->data;
|
||||
MetaWaylandSubsurface *subsurface;
|
||||
|
||||
if (G_NODE_IS_LEAF (n))
|
||||
continue;
|
||||
|
||||
subsurface = META_WAYLAND_SUBSURFACE (subsurface_surface->role);
|
||||
meta_wayland_subsurface_union_geometry (subsurface,
|
||||
0, 0,
|
||||
|
||||
@@ -85,6 +85,7 @@ sync_actor_subsurface_state (MetaWaylandSurface *surface)
|
||||
transform_subsurface_position (surface, &x, &y);
|
||||
|
||||
clutter_actor_set_position (actor, x, y);
|
||||
clutter_actor_set_reactive (actor, TRUE);
|
||||
|
||||
if (surface->buffer_ref.buffer)
|
||||
clutter_actor_show (actor);
|
||||
@@ -198,7 +199,7 @@ meta_wayland_subsurface_union_geometry (MetaWaylandSubsurface *subsurface,
|
||||
MetaWaylandSurface *surface =
|
||||
meta_wayland_surface_role_get_surface (surface_role);
|
||||
MetaRectangle geometry;
|
||||
GNode *n;
|
||||
MetaWaylandSurface *subsurface_surface;
|
||||
|
||||
geometry = (MetaRectangle) {
|
||||
.x = surface->offset_x + surface->sub.x,
|
||||
@@ -209,16 +210,10 @@ meta_wayland_subsurface_union_geometry (MetaWaylandSubsurface *subsurface,
|
||||
|
||||
meta_rectangle_union (out_geometry, &geometry, out_geometry);
|
||||
|
||||
for (n = g_node_first_child (surface->subsurface_branch_node);
|
||||
n;
|
||||
n = g_node_next_sibling (n))
|
||||
META_WAYLAND_SURFACE_FOREACH_SUBSURFACE (surface, subsurface_surface)
|
||||
{
|
||||
MetaWaylandSurface *subsurface_surface = n->data;
|
||||
MetaWaylandSubsurface *subsurface;
|
||||
|
||||
if (G_NODE_IS_LEAF (n))
|
||||
continue;
|
||||
|
||||
subsurface = META_WAYLAND_SUBSURFACE (subsurface_surface->role);
|
||||
meta_wayland_subsurface_union_geometry (subsurface,
|
||||
parent_x + geometry.x,
|
||||
@@ -503,7 +498,6 @@ wl_subcompositor_get_subsurface (struct wl_client *client,
|
||||
MetaWaylandSurface *parent = wl_resource_get_user_data (parent_resource);
|
||||
MetaWindow *toplevel_window;
|
||||
MetaWindowActor *window_actor;
|
||||
MetaSurfaceActor *surface_actor;
|
||||
|
||||
if (surface->wl_subsurface)
|
||||
{
|
||||
@@ -552,9 +546,6 @@ wl_subcompositor_get_subsurface (struct wl_client *client,
|
||||
window_actor = meta_window_actor_wayland_from_surface (surface);
|
||||
if (window_actor)
|
||||
meta_window_actor_wayland_rebuild_surface_tree (window_actor);
|
||||
|
||||
surface_actor = meta_wayland_surface_get_actor (surface);
|
||||
clutter_actor_set_reactive (CLUTTER_ACTOR (surface_actor), TRUE);
|
||||
}
|
||||
|
||||
static const struct wl_subcompositor_interface meta_wayland_subcompositor_interface = {
|
||||
|
||||
@@ -632,20 +632,6 @@ meta_wayland_surface_is_effectively_synchronized (MetaWaylandSurface *surface)
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
parent_surface_state_applied (GNode *subsurface_node,
|
||||
gpointer user_data)
|
||||
{
|
||||
MetaWaylandSurface *surface = subsurface_node->data;
|
||||
MetaWaylandSubsurface *subsurface;
|
||||
|
||||
if (G_NODE_IS_LEAF (subsurface_node))
|
||||
return;
|
||||
|
||||
subsurface = META_WAYLAND_SUBSURFACE (surface->role);
|
||||
meta_wayland_subsurface_parent_state_applied (subsurface);
|
||||
}
|
||||
|
||||
void
|
||||
meta_wayland_surface_cache_pending_frame_callbacks (MetaWaylandSurface *surface,
|
||||
MetaWaylandPendingState *pending)
|
||||
@@ -659,6 +645,7 @@ void
|
||||
meta_wayland_surface_apply_pending_state (MetaWaylandSurface *surface,
|
||||
MetaWaylandPendingState *pending)
|
||||
{
|
||||
MetaWaylandSurface *subsurface_surface;
|
||||
gboolean had_damage = FALSE;
|
||||
|
||||
if (surface->role)
|
||||
@@ -695,11 +682,9 @@ meta_wayland_surface_apply_pending_state (MetaWaylandSurface *surface,
|
||||
if (pending->buffer)
|
||||
{
|
||||
GError *error = NULL;
|
||||
gboolean changed_texture;
|
||||
|
||||
if (!meta_wayland_buffer_attach (pending->buffer,
|
||||
&surface->texture,
|
||||
&changed_texture,
|
||||
&error))
|
||||
{
|
||||
g_warning ("Could not import pending buffer: %s", error->message);
|
||||
@@ -710,24 +695,6 @@ meta_wayland_surface_apply_pending_state (MetaWaylandSurface *surface,
|
||||
g_error_free (error);
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
if (changed_texture && meta_wayland_surface_get_actor (surface))
|
||||
{
|
||||
MetaShapedTexture *stex;
|
||||
CoglTexture *texture;
|
||||
CoglSnippet *snippet;
|
||||
gboolean is_y_inverted;
|
||||
|
||||
stex = meta_surface_actor_get_texture (meta_wayland_surface_get_actor (surface));
|
||||
texture = surface->texture;
|
||||
snippet = meta_wayland_buffer_create_snippet (pending->buffer);
|
||||
is_y_inverted = meta_wayland_buffer_is_y_inverted (pending->buffer);
|
||||
|
||||
meta_shaped_texture_set_texture (stex, texture);
|
||||
meta_shaped_texture_set_snippet (stex, snippet);
|
||||
meta_shaped_texture_set_is_y_inverted (stex, is_y_inverted);
|
||||
g_clear_pointer (&snippet, cogl_object_unref);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -832,10 +799,13 @@ cleanup:
|
||||
|
||||
pending_state_reset (pending);
|
||||
|
||||
g_node_children_foreach (surface->subsurface_branch_node,
|
||||
G_TRAVERSE_ALL,
|
||||
parent_surface_state_applied,
|
||||
NULL);
|
||||
META_WAYLAND_SURFACE_FOREACH_SUBSURFACE (surface, subsurface_surface)
|
||||
{
|
||||
MetaWaylandSubsurface *subsurface;
|
||||
|
||||
subsurface = META_WAYLAND_SUBSURFACE (subsurface_surface->role);
|
||||
meta_wayland_subsurface_parent_state_applied (subsurface);
|
||||
}
|
||||
|
||||
if (had_damage)
|
||||
{
|
||||
@@ -1276,22 +1246,14 @@ meta_wayland_surface_update_outputs (MetaWaylandSurface *surface)
|
||||
static void
|
||||
meta_wayland_surface_update_outputs_recursively (MetaWaylandSurface *surface)
|
||||
{
|
||||
GNode *n;
|
||||
MetaWaylandSurface *subsurface_surface;
|
||||
|
||||
meta_wayland_surface_update_outputs (surface);
|
||||
|
||||
for (n = g_node_first_child (surface->subsurface_branch_node);
|
||||
n;
|
||||
n = g_node_next_sibling (n))
|
||||
{
|
||||
if (G_NODE_IS_LEAF (n))
|
||||
continue;
|
||||
|
||||
meta_wayland_surface_update_outputs_recursively (n->data);
|
||||
}
|
||||
META_WAYLAND_SURFACE_FOREACH_SUBSURFACE (surface, subsurface_surface)
|
||||
meta_wayland_surface_update_outputs_recursively (subsurface_surface);
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
meta_wayland_surface_set_window (MetaWaylandSurface *surface,
|
||||
MetaWindow *window)
|
||||
|
||||
@@ -327,4 +327,38 @@ void meta_wayland_surface_notify_geometry_changed (MetaWaylandSur
|
||||
int meta_wayland_surface_get_width (MetaWaylandSurface *surface);
|
||||
int meta_wayland_surface_get_height (MetaWaylandSurface *surface);
|
||||
|
||||
static inline GNode *
|
||||
meta_get_next_subsurface_sibling (GNode *n)
|
||||
{
|
||||
GNode *next;
|
||||
|
||||
if (!n)
|
||||
return NULL;
|
||||
|
||||
next = g_node_next_sibling (n);
|
||||
if (!next)
|
||||
return NULL;
|
||||
if (!G_NODE_IS_LEAF (next))
|
||||
return next;
|
||||
else
|
||||
return meta_get_next_subsurface_sibling (next);
|
||||
}
|
||||
|
||||
static inline GNode *
|
||||
meta_get_first_subsurface_node (MetaWaylandSurface *surface)
|
||||
{
|
||||
GNode *n;
|
||||
|
||||
n = g_node_first_child (surface->subsurface_branch_node);
|
||||
if (!G_NODE_IS_LEAF (n))
|
||||
return n;
|
||||
else
|
||||
return meta_get_next_subsurface_sibling (n);
|
||||
}
|
||||
|
||||
#define META_WAYLAND_SURFACE_FOREACH_SUBSURFACE(surface, subsurface) \
|
||||
for (GNode *G_PASTE(__n, __LINE__) = meta_get_first_subsurface_node ((surface)); \
|
||||
(subsurface = (G_PASTE (__n, __LINE__) ? G_PASTE (__n, __LINE__)->data : NULL)); \
|
||||
G_PASTE (__n, __LINE__) = meta_get_next_subsurface_sibling (G_PASTE (__n, __LINE__)))
|
||||
|
||||
#endif
|
||||
|
||||
@@ -989,20 +989,13 @@ static gboolean
|
||||
tablet_tool_can_grab_surface (MetaWaylandTabletTool *tool,
|
||||
MetaWaylandSurface *surface)
|
||||
{
|
||||
GNode *n;
|
||||
MetaWaylandSurface *subsurface;
|
||||
|
||||
if (tool->focus_surface == surface)
|
||||
return TRUE;
|
||||
|
||||
for (n = g_node_first_child (surface->subsurface_branch_node);
|
||||
n;
|
||||
n = g_node_next_sibling (n))
|
||||
META_WAYLAND_SURFACE_FOREACH_SUBSURFACE (surface, subsurface)
|
||||
{
|
||||
MetaWaylandSurface *subsurface = n->data;
|
||||
|
||||
if (G_NODE_IS_LEAF (n))
|
||||
continue;
|
||||
|
||||
if (tablet_tool_can_grab_surface (tool, subsurface))
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
@@ -431,7 +431,7 @@ xdg_toplevel_set_fullscreen (struct wl_client *client,
|
||||
{
|
||||
MetaWaylandOutput *output = wl_resource_get_user_data (output_resource);
|
||||
|
||||
if (output)
|
||||
if (output && output->logical_monitor)
|
||||
{
|
||||
meta_window_move_to_monitor (window,
|
||||
output->logical_monitor->number);
|
||||
|
||||
@@ -562,7 +562,7 @@ meta_xwayland_data_source_fetch_mimetype_list (MetaWaylandDataSource *source,
|
||||
XGetWindowProperty (xdisplay, window, prop,
|
||||
0, /* offset */
|
||||
0x1fffffff, /* length */
|
||||
True, /* delete */
|
||||
False, /* delete */
|
||||
AnyPropertyType,
|
||||
&type_ret,
|
||||
&format_ret,
|
||||
@@ -787,6 +787,10 @@ meta_xwayland_dnd_handle_client_message (MetaWaylandCompositor *compositor,
|
||||
xdnd_atoms[ATOM_DND_TYPE_LIST]);
|
||||
}
|
||||
|
||||
meta_wayland_data_source_set_actions (dnd->source,
|
||||
WL_DATA_DEVICE_MANAGER_DND_ACTION_COPY |
|
||||
WL_DATA_DEVICE_MANAGER_DND_ACTION_MOVE |
|
||||
WL_DATA_DEVICE_MANAGER_DND_ACTION_ASK);
|
||||
meta_wayland_drag_grab_set_focus (drag_grab, dnd->focus_surface);
|
||||
return TRUE;
|
||||
}
|
||||
@@ -806,7 +810,7 @@ meta_xwayland_dnd_handle_client_message (MetaWaylandCompositor *compositor,
|
||||
clutter_event_set_time (motion, dnd->last_motion_time);
|
||||
|
||||
action = atom_to_action ((Atom) event->data.l[4]);
|
||||
meta_wayland_data_source_set_actions (dnd->source, action);
|
||||
meta_wayland_data_source_set_user_action (dnd->source, action);
|
||||
|
||||
meta_wayland_surface_drag_dest_motion (drag_focus, motion);
|
||||
xdnd_send_status (dnd, (Window) event->data.l[0],
|
||||
|
||||
@@ -1734,11 +1734,21 @@ process_selection_event (MetaX11Display *x11_display,
|
||||
|
||||
handled |= meta_x11_selection_handle_event (x11_display, event);
|
||||
|
||||
for (l = x11_display->selection.input_streams; l && !handled; l = l->next)
|
||||
handled |= meta_x11_selection_input_stream_xevent (l->data, event);
|
||||
for (l = x11_display->selection.input_streams; l && !handled;)
|
||||
{
|
||||
GList *next = l->next;
|
||||
|
||||
for (l = x11_display->selection.output_streams; l && !handled; l = l->next)
|
||||
handled |= meta_x11_selection_output_stream_xevent (l->data, event);
|
||||
handled |= meta_x11_selection_input_stream_xevent (l->data, event);
|
||||
l = next;
|
||||
}
|
||||
|
||||
for (l = x11_display->selection.output_streams; l && !handled;)
|
||||
{
|
||||
GList *next = l->next;
|
||||
|
||||
handled |= meta_x11_selection_output_stream_xevent (l->data, event);
|
||||
l = next;
|
||||
}
|
||||
|
||||
return handled;
|
||||
}
|
||||
|
||||
@@ -261,6 +261,20 @@ meta_x11_selection_input_stream_close_finish (GInputStream *stream,
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static void
|
||||
meta_x11_selection_input_stream_dispose (GObject *object)
|
||||
{
|
||||
MetaX11SelectionInputStream *stream =
|
||||
META_X11_SELECTION_INPUT_STREAM (object);
|
||||
MetaX11SelectionInputStreamPrivate *priv =
|
||||
meta_x11_selection_input_stream_get_instance_private (stream);
|
||||
|
||||
priv->x11_display->selection.input_streams =
|
||||
g_list_remove (priv->x11_display->selection.input_streams, stream);
|
||||
|
||||
G_OBJECT_CLASS (meta_x11_selection_input_stream_parent_class)->dispose (object);
|
||||
}
|
||||
|
||||
static void
|
||||
meta_x11_selection_input_stream_finalize (GObject *object)
|
||||
{
|
||||
@@ -284,6 +298,7 @@ meta_x11_selection_input_stream_class_init (MetaX11SelectionInputStreamClass *kl
|
||||
GObjectClass *object_class = G_OBJECT_CLASS (klass);
|
||||
GInputStreamClass *istream_class = G_INPUT_STREAM_CLASS (klass);
|
||||
|
||||
object_class->dispose = meta_x11_selection_input_stream_dispose;
|
||||
object_class->finalize = meta_x11_selection_input_stream_finalize;
|
||||
|
||||
istream_class->read_fn = meta_x11_selection_input_stream_read;
|
||||
|
||||
@@ -57,12 +57,15 @@ struct _MetaX11SelectionOutputStreamPrivate
|
||||
|
||||
guint incr : 1;
|
||||
guint delete_pending : 1;
|
||||
guint pipe_error : 1;
|
||||
};
|
||||
|
||||
G_DEFINE_TYPE_WITH_PRIVATE (MetaX11SelectionOutputStream,
|
||||
meta_x11_selection_output_stream,
|
||||
G_TYPE_OUTPUT_STREAM);
|
||||
|
||||
static size_t get_element_size (int format);
|
||||
|
||||
static void
|
||||
meta_x11_selection_output_stream_notify_selection (MetaX11SelectionOutputStream *stream)
|
||||
{
|
||||
@@ -100,6 +103,9 @@ meta_x11_selection_output_stream_can_flush (MetaX11SelectionOutputStream *stream
|
||||
|
||||
if (priv->delete_pending)
|
||||
return FALSE;
|
||||
if (!g_output_stream_is_closing (G_OUTPUT_STREAM (stream)) &&
|
||||
priv->data->len < get_element_size (priv->format))
|
||||
return FALSE;
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
@@ -113,7 +119,7 @@ get_max_request_size (MetaX11Display *display)
|
||||
if (size <= 0)
|
||||
size = XMaxRequestSize (display->xdisplay);
|
||||
|
||||
return size - 100;
|
||||
return (size - 100) * 4;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
@@ -123,7 +129,12 @@ meta_x11_selection_output_stream_needs_flush_unlocked (MetaX11SelectionOutputStr
|
||||
meta_x11_selection_output_stream_get_instance_private (stream);
|
||||
|
||||
if (priv->data->len == 0)
|
||||
return FALSE;
|
||||
{
|
||||
if (priv->incr)
|
||||
return g_output_stream_is_closing (G_OUTPUT_STREAM (stream));
|
||||
else
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if (g_output_stream_is_closing (G_OUTPUT_STREAM (stream)))
|
||||
return TRUE;
|
||||
@@ -171,13 +182,34 @@ get_element_size (int format)
|
||||
}
|
||||
}
|
||||
|
||||
static gboolean
|
||||
meta_x11_selection_output_stream_check_pipe (MetaX11SelectionOutputStream *stream,
|
||||
GError **error)
|
||||
{
|
||||
MetaX11SelectionOutputStreamPrivate *priv =
|
||||
meta_x11_selection_output_stream_get_instance_private (stream);
|
||||
|
||||
if (priv->pipe_error)
|
||||
{
|
||||
g_set_error (error,
|
||||
G_IO_ERROR,
|
||||
G_IO_ERROR_BROKEN_PIPE,
|
||||
"Connection with client was broken");
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static void
|
||||
meta_x11_selection_output_stream_perform_flush (MetaX11SelectionOutputStream *stream)
|
||||
{
|
||||
MetaX11SelectionOutputStreamPrivate *priv =
|
||||
meta_x11_selection_output_stream_get_instance_private (stream);
|
||||
Display *xdisplay;
|
||||
size_t element_size, n_elements;
|
||||
size_t element_size, n_elements, max_size;
|
||||
gboolean first_chunk = FALSE;
|
||||
int error_code;
|
||||
|
||||
g_assert (!priv->delete_pending);
|
||||
|
||||
@@ -190,8 +222,12 @@ meta_x11_selection_output_stream_perform_flush (MetaX11SelectionOutputStream *st
|
||||
|
||||
element_size = get_element_size (priv->format);
|
||||
n_elements = priv->data->len / element_size;
|
||||
max_size = get_max_request_size (priv->x11_display);
|
||||
|
||||
if (!g_output_stream_is_closing (G_OUTPUT_STREAM (stream)))
|
||||
if (!priv->incr)
|
||||
first_chunk = TRUE;
|
||||
|
||||
if (!priv->incr && priv->data->len > max_size)
|
||||
{
|
||||
XWindowAttributes attrs;
|
||||
|
||||
@@ -207,14 +243,22 @@ meta_x11_selection_output_stream_perform_flush (MetaX11SelectionOutputStream *st
|
||||
XChangeProperty (xdisplay,
|
||||
priv->xwindow,
|
||||
priv->xproperty,
|
||||
XInternAtom (priv->x11_display->xdisplay, "INCR", True),
|
||||
XInternAtom (priv->x11_display->xdisplay, "INCR", False),
|
||||
32,
|
||||
PropModeReplace,
|
||||
(guchar *) &(long) { n_elements },
|
||||
1);
|
||||
priv->delete_pending = TRUE;
|
||||
}
|
||||
else
|
||||
{
|
||||
size_t copy_n_elements;
|
||||
|
||||
if (priv->incr && priv->data->len > 0)
|
||||
priv->delete_pending = TRUE;
|
||||
|
||||
copy_n_elements = MIN (n_elements, max_size / element_size);
|
||||
|
||||
XChangeProperty (xdisplay,
|
||||
priv->xwindow,
|
||||
priv->xproperty,
|
||||
@@ -222,30 +266,45 @@ meta_x11_selection_output_stream_perform_flush (MetaX11SelectionOutputStream *st
|
||||
priv->format,
|
||||
PropModeReplace,
|
||||
priv->data->data,
|
||||
n_elements);
|
||||
g_byte_array_remove_range (priv->data, 0, n_elements * element_size);
|
||||
if (priv->data->len < element_size)
|
||||
priv->flush_requested = FALSE;
|
||||
copy_n_elements);
|
||||
g_byte_array_remove_range (priv->data, 0, copy_n_elements * element_size);
|
||||
}
|
||||
|
||||
meta_x11_selection_output_stream_notify_selection (stream);
|
||||
if (first_chunk)
|
||||
meta_x11_selection_output_stream_notify_selection (stream);
|
||||
|
||||
priv->delete_pending = TRUE;
|
||||
g_cond_broadcast (&priv->cond);
|
||||
g_mutex_unlock (&priv->mutex);
|
||||
|
||||
/* XXX: handle failure here and report EPIPE for future operations on the stream? */
|
||||
if (meta_x11_error_trap_pop_with_return (priv->x11_display))
|
||||
g_warning ("Failed to flush selection output stream");
|
||||
error_code = meta_x11_error_trap_pop_with_return (priv->x11_display);
|
||||
|
||||
if (priv->pending_task)
|
||||
if (error_code != Success)
|
||||
{
|
||||
char error_str[100];
|
||||
|
||||
priv->flush_requested = FALSE;
|
||||
priv->delete_pending = FALSE;
|
||||
priv->pipe_error = TRUE;
|
||||
|
||||
if (priv->pending_task)
|
||||
{
|
||||
XGetErrorText (xdisplay, error_code, error_str, sizeof (error_str));
|
||||
g_task_return_new_error (priv->pending_task,
|
||||
G_IO_ERROR,
|
||||
G_IO_ERROR_BROKEN_PIPE,
|
||||
"Failed to flush selection output stream: %s",
|
||||
error_str);
|
||||
g_clear_object (&priv->pending_task);
|
||||
}
|
||||
}
|
||||
else if (priv->pending_task && priv->data->len == 0 && !priv->delete_pending)
|
||||
{
|
||||
size_t result;
|
||||
|
||||
priv->flush_requested = FALSE;
|
||||
result = GPOINTER_TO_SIZE (g_task_get_task_data (priv->pending_task));
|
||||
g_task_return_int (priv->pending_task, result);
|
||||
g_object_unref (priv->pending_task);
|
||||
priv->pending_task = NULL;
|
||||
g_clear_object (&priv->pending_task);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -254,12 +313,17 @@ meta_x11_selection_output_stream_invoke_flush (gpointer data)
|
||||
{
|
||||
MetaX11SelectionOutputStream *stream =
|
||||
META_X11_SELECTION_OUTPUT_STREAM (data);
|
||||
MetaX11SelectionOutputStreamPrivate *priv =
|
||||
meta_x11_selection_output_stream_get_instance_private (stream);
|
||||
|
||||
if (meta_x11_selection_output_stream_needs_flush (stream) &&
|
||||
meta_x11_selection_output_stream_can_flush (stream))
|
||||
meta_x11_selection_output_stream_perform_flush (stream);
|
||||
|
||||
return G_SOURCE_REMOVE;
|
||||
if (priv->delete_pending || priv->data->len > 0)
|
||||
return G_SOURCE_CONTINUE;
|
||||
else
|
||||
return G_SOURCE_REMOVE;
|
||||
}
|
||||
|
||||
static gssize
|
||||
@@ -274,6 +338,9 @@ meta_x11_selection_output_stream_write (GOutputStream *output_stream,
|
||||
MetaX11SelectionOutputStreamPrivate *priv =
|
||||
meta_x11_selection_output_stream_get_instance_private (stream);
|
||||
|
||||
if (!meta_x11_selection_output_stream_check_pipe (stream, error))
|
||||
return -1;
|
||||
|
||||
g_mutex_lock (&priv->mutex);
|
||||
g_byte_array_append (priv->data, buffer, count);
|
||||
g_mutex_unlock (&priv->mutex);
|
||||
@@ -301,12 +368,19 @@ meta_x11_selection_output_stream_write_async (GOutputStream *output_stream
|
||||
META_X11_SELECTION_OUTPUT_STREAM (output_stream);
|
||||
MetaX11SelectionOutputStreamPrivate *priv =
|
||||
meta_x11_selection_output_stream_get_instance_private (stream);
|
||||
GError *error = NULL;
|
||||
GTask *task;
|
||||
|
||||
task = g_task_new (stream, cancellable, callback, user_data);
|
||||
g_task_set_source_tag (task, meta_x11_selection_output_stream_write_async);
|
||||
g_task_set_priority (task, io_priority);
|
||||
|
||||
if (!meta_x11_selection_output_stream_check_pipe (stream, &error))
|
||||
{
|
||||
g_task_return_error (task, error);
|
||||
return;
|
||||
}
|
||||
|
||||
g_mutex_lock (&priv->mutex);
|
||||
g_byte_array_append (priv->data, buffer, count);
|
||||
g_mutex_unlock (&priv->mutex);
|
||||
@@ -317,16 +391,11 @@ meta_x11_selection_output_stream_write_async (GOutputStream *output_stream
|
||||
g_object_unref (task);
|
||||
return;
|
||||
}
|
||||
else if (!meta_x11_selection_output_stream_can_flush (stream))
|
||||
{
|
||||
g_assert (priv->pending_task == NULL);
|
||||
priv->pending_task = task;
|
||||
g_task_set_task_data (task, GSIZE_TO_POINTER (count), NULL);
|
||||
return;
|
||||
}
|
||||
else
|
||||
{
|
||||
meta_x11_selection_output_stream_perform_flush (stream);
|
||||
if (meta_x11_selection_output_stream_can_flush (stream))
|
||||
meta_x11_selection_output_stream_perform_flush (stream);
|
||||
|
||||
g_task_return_int (task, count);
|
||||
g_object_unref (task);
|
||||
return;
|
||||
@@ -354,7 +423,7 @@ meta_x11_selection_output_request_flush (MetaX11SelectionOutputStream *stream)
|
||||
|
||||
g_mutex_lock (&priv->mutex);
|
||||
|
||||
if (priv->data->len >= get_element_size (priv->format))
|
||||
if (priv->data->len > 0)
|
||||
priv->flush_requested = TRUE;
|
||||
|
||||
needs_flush = meta_x11_selection_output_stream_needs_flush_unlocked (stream);
|
||||
@@ -373,6 +442,8 @@ meta_x11_selection_output_stream_flush (GOutputStream *output_stream,
|
||||
MetaX11SelectionOutputStreamPrivate *priv =
|
||||
meta_x11_selection_output_stream_get_instance_private (stream);
|
||||
|
||||
if (!meta_x11_selection_output_stream_check_pipe (stream, error))
|
||||
return FALSE;
|
||||
if (!meta_x11_selection_output_request_flush (stream))
|
||||
return TRUE;
|
||||
|
||||
@@ -398,12 +469,19 @@ meta_x11_selection_output_stream_flush_async (GOutputStream *output_stream
|
||||
META_X11_SELECTION_OUTPUT_STREAM (output_stream);
|
||||
MetaX11SelectionOutputStreamPrivate *priv =
|
||||
meta_x11_selection_output_stream_get_instance_private (stream);
|
||||
GError *error = NULL;
|
||||
GTask *task;
|
||||
|
||||
task = g_task_new (stream, cancellable, callback, user_data);
|
||||
g_task_set_source_tag (task, meta_x11_selection_output_stream_flush_async);
|
||||
g_task_set_priority (task, io_priority);
|
||||
|
||||
if (!meta_x11_selection_output_stream_check_pipe (stream, &error))
|
||||
{
|
||||
g_task_return_error (task, error);
|
||||
return;
|
||||
}
|
||||
|
||||
if (!meta_x11_selection_output_stream_can_flush (stream))
|
||||
{
|
||||
if (meta_x11_selection_output_request_flush (stream))
|
||||
@@ -420,10 +498,9 @@ meta_x11_selection_output_stream_flush_async (GOutputStream *output_stream
|
||||
}
|
||||
}
|
||||
|
||||
g_assert (priv->pending_task == NULL);
|
||||
priv->pending_task = task;
|
||||
meta_x11_selection_output_stream_perform_flush (stream);
|
||||
g_task_return_boolean (task, TRUE);
|
||||
g_object_unref (task);
|
||||
return;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
@@ -489,6 +566,20 @@ meta_x11_selection_output_stream_close_finish (GOutputStream *stream,
|
||||
return g_task_propagate_boolean (G_TASK (result), error);
|
||||
}
|
||||
|
||||
static void
|
||||
meta_x11_selection_output_stream_dispose (GObject *object)
|
||||
{
|
||||
MetaX11SelectionOutputStream *stream =
|
||||
META_X11_SELECTION_OUTPUT_STREAM (object);
|
||||
MetaX11SelectionOutputStreamPrivate *priv =
|
||||
meta_x11_selection_output_stream_get_instance_private (stream);
|
||||
|
||||
priv->x11_display->selection.output_streams =
|
||||
g_list_remove (priv->x11_display->selection.output_streams, stream);
|
||||
|
||||
G_OBJECT_CLASS (meta_x11_selection_output_stream_parent_class)->dispose (object);
|
||||
}
|
||||
|
||||
static void
|
||||
meta_x11_selection_output_stream_finalize (GObject *object)
|
||||
{
|
||||
@@ -514,6 +605,7 @@ meta_x11_selection_output_stream_class_init (MetaX11SelectionOutputStreamClass *
|
||||
GObjectClass *object_class = G_OBJECT_CLASS (klass);
|
||||
GOutputStreamClass *output_stream_class = G_OUTPUT_STREAM_CLASS (klass);
|
||||
|
||||
object_class->dispose = meta_x11_selection_output_stream_dispose;
|
||||
object_class->finalize = meta_x11_selection_output_stream_finalize;
|
||||
|
||||
output_stream_class->write_fn = meta_x11_selection_output_stream_write;
|
||||
|
||||
@@ -23,10 +23,22 @@
|
||||
|
||||
#include <gdk/gdkx.h>
|
||||
|
||||
#include "core/meta-selection-private.h"
|
||||
#include "meta/meta-selection-source-memory.h"
|
||||
#include "x11/meta-selection-source-x11-private.h"
|
||||
#include "x11/meta-x11-selection-output-stream-private.h"
|
||||
#include "x11/meta-x11-selection-private.h"
|
||||
|
||||
#define UTF8_STRING_MIMETYPE "text/plain;charset=utf-8"
|
||||
#define STRING_MIMETYPE "text/plain"
|
||||
|
||||
/* Set an arbitrary (although generous) threshold to determine whether a
|
||||
* XFixesSelectionNotify corresponds to a XSetSelectionOwner from another
|
||||
* client. The selection timestamp is not updated if the owner client is
|
||||
* closed.
|
||||
*/
|
||||
#define SELECTION_CLEARED_BY_CLIENT(e) (e->timestamp - e->selection_timestamp < 50)
|
||||
|
||||
static gboolean
|
||||
atom_to_selection_type (Display *xdisplay,
|
||||
Atom selection,
|
||||
@@ -141,6 +153,45 @@ transfer_cb (MetaSelection *selection,
|
||||
g_object_unref (output);
|
||||
}
|
||||
|
||||
static char *
|
||||
meta_x11_selection_find_target (MetaX11Display *x11_display,
|
||||
MetaSelection *selection,
|
||||
MetaSelectionType selection_type,
|
||||
Atom selection_atom)
|
||||
{
|
||||
GList* mimetypes = NULL;
|
||||
const gchar *atom_name;
|
||||
char *retval;
|
||||
|
||||
mimetypes = meta_selection_get_mimetypes (selection, selection_type);
|
||||
atom_name = gdk_x11_get_xatom_name (selection_atom);
|
||||
|
||||
if (g_list_find_custom (mimetypes, atom_name, (GCompareFunc) g_strcmp0))
|
||||
{
|
||||
retval = g_strdup (atom_name);
|
||||
}
|
||||
else if (strcmp (atom_name, "UTF8_STRING") == 0 &&
|
||||
g_list_find_custom (mimetypes, UTF8_STRING_MIMETYPE,
|
||||
(GCompareFunc) g_strcmp0))
|
||||
{
|
||||
retval = g_strdup (UTF8_STRING_MIMETYPE);
|
||||
}
|
||||
else if (strcmp (atom_name, "STRING") == 0 &&
|
||||
g_list_find_custom (mimetypes, STRING_MIMETYPE,
|
||||
(GCompareFunc) g_strcmp0))
|
||||
{
|
||||
retval = g_strdup (STRING_MIMETYPE);
|
||||
}
|
||||
else
|
||||
{
|
||||
retval = NULL;
|
||||
}
|
||||
|
||||
g_list_free_full (mimetypes, g_free);
|
||||
|
||||
return retval;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
meta_x11_selection_handle_selection_request (MetaX11Display *x11_display,
|
||||
XEvent *xevent)
|
||||
@@ -197,15 +248,12 @@ meta_x11_selection_handle_selection_request (MetaX11Display *x11_display,
|
||||
}
|
||||
else
|
||||
{
|
||||
gboolean has_target;
|
||||
g_autofree char *target = NULL;
|
||||
|
||||
mimetypes = meta_selection_get_mimetypes (selection, selection_type);
|
||||
has_target = g_list_find_custom (mimetypes,
|
||||
gdk_x11_get_xatom_name (event->target),
|
||||
(GCompareFunc) g_strcmp0) != NULL;
|
||||
g_list_free_full (mimetypes, g_free);
|
||||
target = meta_x11_selection_find_target (x11_display, selection,
|
||||
selection_type, event->target);
|
||||
|
||||
if (has_target)
|
||||
if (target != NULL)
|
||||
{
|
||||
output = meta_x11_selection_output_stream_new (x11_display,
|
||||
event->requestor,
|
||||
@@ -217,7 +265,7 @@ meta_x11_selection_handle_selection_request (MetaX11Display *x11_display,
|
||||
|
||||
meta_selection_transfer_async (selection,
|
||||
selection_type,
|
||||
gdk_x11_get_xatom_name (event->target),
|
||||
target,
|
||||
-1,
|
||||
output,
|
||||
NULL,
|
||||
@@ -226,7 +274,9 @@ meta_x11_selection_handle_selection_request (MetaX11Display *x11_display,
|
||||
return TRUE;
|
||||
}
|
||||
else
|
||||
send_selection_notify (event, FALSE);
|
||||
{
|
||||
send_selection_notify (event, FALSE);
|
||||
}
|
||||
}
|
||||
|
||||
return FALSE;
|
||||
@@ -254,8 +304,9 @@ source_new_cb (GObject *object,
|
||||
source = meta_selection_source_x11_new_finish (res, &error);
|
||||
if (source)
|
||||
{
|
||||
meta_selection_set_owner (selection, selection_type, source);
|
||||
g_set_object (&x11_display->selection.owners[selection_type], source);
|
||||
meta_selection_set_owner (selection, selection_type, source);
|
||||
g_object_unref (source);
|
||||
}
|
||||
else if (!g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED))
|
||||
{
|
||||
@@ -288,16 +339,27 @@ meta_x11_selection_handle_xfixes_selection_notify (MetaX11Display *x11_display,
|
||||
|
||||
x11_display->selection.cancellables[selection_type] = g_cancellable_new ();
|
||||
|
||||
if (event->owner == None)
|
||||
if (event->owner == None && x11_display->selection.owners[selection_type])
|
||||
{
|
||||
if (x11_display->selection.owners[selection_type])
|
||||
if (SELECTION_CLEARED_BY_CLIENT (event))
|
||||
{
|
||||
MetaSelectionSource *source;
|
||||
|
||||
/* Replace with an empty owner */
|
||||
source = g_object_new (META_TYPE_SELECTION_SOURCE_MEMORY, NULL);
|
||||
g_set_object (&x11_display->selection.owners[selection_type], source);
|
||||
meta_selection_set_owner (selection, selection_type, source);
|
||||
g_object_unref (source);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* An X client went away, clear the selection */
|
||||
meta_selection_unset_owner (selection, selection_type,
|
||||
x11_display->selection.owners[selection_type]);
|
||||
g_clear_object (&x11_display->selection.owners[selection_type]);
|
||||
}
|
||||
}
|
||||
else if (event->owner != x11_display->selection.xwindow)
|
||||
else if (event->owner != None && event->owner != x11_display->selection.xwindow)
|
||||
{
|
||||
SourceNewData *data;
|
||||
|
||||
@@ -331,14 +393,13 @@ meta_x11_selection_handle_event (MetaX11Display *x11_display,
|
||||
}
|
||||
|
||||
static void
|
||||
owner_changed_cb (MetaSelection *selection,
|
||||
MetaSelectionType selection_type,
|
||||
MetaSelectionSource *new_owner,
|
||||
MetaX11Display *x11_display)
|
||||
notify_selection_owner (MetaX11Display *x11_display,
|
||||
MetaSelectionType selection_type,
|
||||
MetaSelectionSource *new_owner)
|
||||
{
|
||||
Display *xdisplay = x11_display->xdisplay;
|
||||
|
||||
if (new_owner && !META_IS_SELECTION_SOURCE_X11 (new_owner))
|
||||
if (new_owner && new_owner != x11_display->selection.owners[selection_type])
|
||||
{
|
||||
if (x11_display->selection.cancellables[selection_type])
|
||||
{
|
||||
@@ -361,6 +422,7 @@ meta_x11_selection_init (MetaX11Display *x11_display)
|
||||
{
|
||||
XSetWindowAttributes attributes = { 0 };
|
||||
MetaDisplay *display = meta_get_display ();
|
||||
MetaSelection *selection;
|
||||
guint mask, i;
|
||||
|
||||
attributes.event_mask = PropertyChangeMask | SubstructureNotifyMask;
|
||||
@@ -381,18 +443,24 @@ meta_x11_selection_init (MetaX11Display *x11_display)
|
||||
XFixesSelectionWindowDestroyNotifyMask |
|
||||
XFixesSelectionClientCloseNotifyMask;
|
||||
|
||||
selection = meta_display_get_selection (display);
|
||||
|
||||
for (i = 0; i < META_N_SELECTION_TYPES; i++)
|
||||
{
|
||||
MetaSelectionSource *owner;
|
||||
|
||||
XFixesSelectSelectionInput (x11_display->xdisplay,
|
||||
x11_display->selection.xwindow,
|
||||
selection_to_atom (i, x11_display->xdisplay),
|
||||
mask);
|
||||
owner = meta_selection_get_current_owner (selection, i);
|
||||
notify_selection_owner (x11_display, i, owner);
|
||||
}
|
||||
|
||||
g_signal_connect (meta_display_get_selection (display),
|
||||
"owner-changed",
|
||||
G_CALLBACK (owner_changed_cb),
|
||||
x11_display);
|
||||
g_signal_connect_swapped (selection,
|
||||
"owner-changed",
|
||||
G_CALLBACK (notify_selection_owner),
|
||||
x11_display);
|
||||
}
|
||||
|
||||
void
|
||||
@@ -401,7 +469,7 @@ meta_x11_selection_shutdown (MetaX11Display *x11_display)
|
||||
MetaDisplay *display = meta_get_display ();
|
||||
|
||||
g_signal_handlers_disconnect_by_func (meta_display_get_selection (display),
|
||||
owner_changed_cb,
|
||||
notify_selection_owner,
|
||||
x11_display);
|
||||
if (x11_display->selection.xwindow != None)
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user