Browse Source

UI: Fix Qt call on UI thread from graphics thread

Calling `devicePixelRatioF` from any thread but the main UI thread
triggers thread-safety warnings at runtime on macOS, because Qt uses
NSView calls to determine the value.

NSView calls are only allowed to be made from the main thread on macOS,
so instead the value is stored as a property of the OBSQTDisplay at
initialization, to be retrieved from the preview object later.

Static functions that do not have access to the preview object have the
pixel ratio passed in their call signature.
PatTheMav 3 năm trước cách đây
mục cha
commit
f1cf3ff141
3 tập tin đã thay đổi với 31 bổ sung22 xóa
  1. 7 0
      UI/window-basic-main.cpp
  2. 4 0
      UI/window-basic-main.hpp
  3. 20 22
      UI/window-basic-preview.cpp

+ 7 - 0
UI/window-basic-main.cpp

@@ -319,7 +319,9 @@ OBSBasic::OBSBasic(QWidget *parent)
 			ResizePreview(ovi.base_width, ovi.base_height);
 
 		UpdateContextBarVisibility();
+		dpi = devicePixelRatioF();
 	};
+	dpi = devicePixelRatioF();
 
 	connect(windowHandle(), &QWindow::screenChanged, displayResize);
 	connect(ui->preview, &OBSQTDisplay::DisplayResized, displayResize);
@@ -10241,3 +10243,8 @@ void OBSBasic::UpdatePreviewSpacingHelpers()
 	drawSpacingHelpers = config_get_bool(
 		App()->GlobalConfig(), "BasicWindow", "SpacingHelpersEnabled");
 }
+
+float OBSBasic::GetDevicePixelRatio()
+{
+	return dpi;
+}

+ 4 - 0
UI/window-basic-main.hpp

@@ -636,6 +636,8 @@ private:
 	void UpdatePreviewSpacingHelpers();
 	bool drawSpacingHelpers = true;
 
+	float GetDevicePixelRatio();
+
 public slots:
 	void DeferSaveBegin();
 	void DeferSaveEnd();
@@ -844,6 +846,8 @@ private:
 
 	OBSSource prevFTBSource = nullptr;
 
+	float dpi = 1.0;
+
 public:
 	OBSSource GetProgramSource();
 	OBSScene GetCurrentScene();

+ 20 - 22
UI/window-basic-preview.cpp

@@ -40,7 +40,7 @@ OBSBasicPreview::~OBSBasicPreview()
 vec2 OBSBasicPreview::GetMouseEventPos(QMouseEvent *event)
 {
 	OBSBasic *main = reinterpret_cast<OBSBasic *>(App()->GetMainWindow());
-	float pixelRatio = main->devicePixelRatioF();
+	float pixelRatio = main->GetDevicePixelRatio();
 	float scale = pixelRatio / main->previewScale;
 	QPoint qtPos = event->pos();
 	vec2 pos;
@@ -459,7 +459,7 @@ void OBSBasicPreview::GetStretchHandleData(const vec2 &pos, bool ignoreGroup)
 	if (!scene)
 		return;
 
-	float scale = main->previewScale / main->devicePixelRatioF();
+	float scale = main->previewScale / main->GetDevicePixelRatio();
 	vec2 scaled_pos = pos;
 	vec2_divf(&scaled_pos, &scaled_pos, scale);
 	HandleFindData data(scaled_pos, scale);
@@ -592,7 +592,7 @@ void OBSBasicPreview::mousePressEvent(QMouseEvent *event)
 	}
 
 	OBSBasic *main = reinterpret_cast<OBSBasic *>(App()->GetMainWindow());
-	float pixelRatio = main->devicePixelRatioF();
+	float pixelRatio = main->GetDevicePixelRatio();
 	float x = pos.x() - main->previewX / pixelRatio;
 	float y = pos.y() - main->previewY / pixelRatio;
 	Qt::KeyboardModifiers modifiers = QGuiApplication::keyboardModifiers();
@@ -1591,7 +1591,7 @@ void OBSBasicPreview::mouseMoveEvent(QMouseEvent *event)
 	QPointF qtPos = event->localPos();
 #endif
 
-	float pixelRatio = main->devicePixelRatioF();
+	float pixelRatio = main->GetDevicePixelRatio();
 
 	if (scrollMode && event->buttons() == Qt::LeftButton) {
 		scrollingOffset.x += pixelRatio * (qtPos.x() - scrollingFrom.x);
@@ -1671,7 +1671,7 @@ void OBSBasicPreview::mouseMoveEvent(QMouseEvent *event)
 			mousePos = pos;
 			OBSBasic *main = reinterpret_cast<OBSBasic *>(
 				App()->GetMainWindow());
-			float scale = main->devicePixelRatioF();
+			float scale = main->GetDevicePixelRatio();
 			float x = qtPos.x() - main->previewX / scale;
 			float y = qtPos.y() - main->previewY / scale;
 			vec2_set(&startPos, x, y);
@@ -1716,12 +1716,10 @@ static void DrawLine(float x1, float y1, float x2, float y2, float thickness,
 	gs_vertexbuffer_destroy(line);
 }
 
-static void DrawSquareAtPos(float x, float y)
+static void DrawSquareAtPos(float x, float y, float pixelRatio)
 {
 	OBSBasic *main = OBSBasic::Get();
 
-	float pixelRatio = main->devicePixelRatioF();
-
 	struct vec3 pos;
 	vec3_set(&pos, x, y, 0.0f);
 
@@ -1742,12 +1740,11 @@ static void DrawSquareAtPos(float x, float y)
 	gs_matrix_pop();
 }
 
-static void DrawRotationHandle(gs_vertbuffer_t *circle, float rot)
+static void DrawRotationHandle(gs_vertbuffer_t *circle, float rot,
+			       float pixelRatio)
 {
 	OBSBasic *main = OBSBasic::Get();
 
-	float pixelRatio = main->devicePixelRatioF();
-
 	struct vec3 pos;
 	vec3_set(&pos, 0.5f, 0.0f, 0.0f);
 
@@ -1985,7 +1982,7 @@ bool OBSBasicPreview::DrawSelectedItem(obs_scene_t *scene,
 
 	OBSBasic *main = OBSBasic::Get();
 
-	float pixelRatio = main->devicePixelRatioF();
+	float pixelRatio = main->GetDevicePixelRatio();
 
 	bool hovered = false;
 	{
@@ -2100,14 +2097,14 @@ bool OBSBasicPreview::DrawSelectedItem(obs_scene_t *scene,
 	gs_effect_set_vec4(colParam, &red);
 
 	if (selected) {
-		DrawSquareAtPos(0.0f, 0.0f);
-		DrawSquareAtPos(0.0f, 1.0f);
-		DrawSquareAtPos(1.0f, 0.0f);
-		DrawSquareAtPos(1.0f, 1.0f);
-		DrawSquareAtPos(0.5f, 0.0f);
-		DrawSquareAtPos(0.0f, 0.5f);
-		DrawSquareAtPos(0.5f, 1.0f);
-		DrawSquareAtPos(1.0f, 0.5f);
+		DrawSquareAtPos(0.0f, 0.0f, pixelRatio);
+		DrawSquareAtPos(0.0f, 1.0f, pixelRatio);
+		DrawSquareAtPos(1.0f, 0.0f, pixelRatio);
+		DrawSquareAtPos(1.0f, 1.0f, pixelRatio);
+		DrawSquareAtPos(0.5f, 0.0f, pixelRatio);
+		DrawSquareAtPos(0.0f, 0.5f, pixelRatio);
+		DrawSquareAtPos(0.5f, 1.0f, pixelRatio);
+		DrawSquareAtPos(1.0f, 0.5f, pixelRatio);
 
 		if (!prev->circleFill) {
 			gs_render_start(true);
@@ -2125,7 +2122,8 @@ bool OBSBasicPreview::DrawSelectedItem(obs_scene_t *scene,
 			prev->circleFill = gs_render_save();
 		}
 
-		DrawRotationHandle(prev->circleFill, info.rot + prev->groupRot);
+		DrawRotationHandle(prev->circleFill, info.rot + prev->groupRot,
+				   pixelRatio);
 	}
 
 	gs_matrix_pop();
@@ -2141,7 +2139,7 @@ bool OBSBasicPreview::DrawSelectionBox(float x1, float y1, float x2, float y2,
 {
 	OBSBasic *main = OBSBasic::Get();
 
-	float pixelRatio = main->devicePixelRatioF();
+	float pixelRatio = main->GetDevicePixelRatio();
 
 	x1 = std::round(x1);
 	x2 = std::round(x2);