Skip to content

Commit

Permalink
Fix #823: Support virtual coordinate in mozc_renderer to fix its wind…
Browse files Browse the repository at this point in the history
…ow position on HiDPI displays (#876)

Qt6 applications use virtual coordinates. Since IBus uses the device-pixel native coordinate system to represent a position of a pre-edit area, mozc_renderer converts it to the virtual coordinate.

PiperOrigin-RevId: 616104261
  • Loading branch information
ftake authored Mar 15, 2024
1 parent 769ddfe commit 37424fc
Showing 1 changed file with 58 additions and 2 deletions.
60 changes: 58 additions & 2 deletions src/renderer/qt/qt_window_manager.cc
Original file line number Diff line number Diff line change
Expand Up @@ -339,13 +339,69 @@ void FillCandidates(const commands::Candidates &candidates,
const int width = kColumn0Width + max_width1 + max_width2 + kColumn3Width;
table->resize(width, total_height);
}

class VirtualRect {
public:
static VirtualRect FromNativeRect(const Rect &native_rect) {
for (const QScreen *screen : QGuiApplication::screens()) {
const Rect rect = TranslateToVirtual(screen, native_rect);
const QRect screen_rect = screen->geometry();

// Use top left to locate a screen
if (screen_rect.contains(rect.Left(), rect.Top())) {
return VirtualRect(rect, mozc::renderer::GetRect(screen->geometry()));
}
}

// fall back to primary screen
// TODO: Return the nearest monitor rect instead.
// See GetMonitorRect
const QScreen *screen = QGuiApplication::primaryScreen();
const Rect rect = TranslateToVirtual(screen, native_rect);
return VirtualRect(rect, mozc::renderer::GetRect(screen->geometry()));
}

Rect GetRect() const { return rect_; }

Rect GetMonitorRect() const { return monitor_rect_; }

private:
VirtualRect(const Rect &rect, const Rect &monitor_rect)
: rect_(rect), monitor_rect_(monitor_rect) {}

static Rect TranslateToVirtual(const QScreen *screen,
const Rect &native_rect) {
const double device_pixel_ratio = screen->devicePixelRatio();
// screen_left, screen_top have the same value in both virtual and native
// coordinate
const int screen_left = screen->geometry().x();
const int screen_top = screen->geometry().y();
const int dx = native_rect.Left() - screen_left;
const int dy = native_rect.Top() - screen_top;
const int vx =
static_cast<int>(std::floor(dx / device_pixel_ratio)) + screen_left;
const int vy =
static_cast<int>(std::floor(dy / device_pixel_ratio)) + screen_top;

return Rect(vx, vy, native_rect.Width() / device_pixel_ratio,
native_rect.Height() / device_pixel_ratio);
}

Rect rect_;
Rect monitor_rect_;
};
} // namespace

Point QtWindowManager::GetWindowPosition(
const commands::RendererCommand &command, const Size &win_size) {
const Rect preedit_rect = GetRect(command.preedit_rectangle());
const Rect native_preedit_rect = GetRect(command.preedit_rectangle());
// Qt6 applications use virtual coordinates. Since IBus uses the device-pixel
// native coordinate system, we need to translate a received rect to virtual.
const VirtualRect virtual_rect =
VirtualRect::FromNativeRect(native_preedit_rect);
const Rect preedit_rect = virtual_rect.GetRect();
const Point win_pos = Point(preedit_rect.Left(), preedit_rect.Bottom());
const Rect monitor_rect = GetMonitorRect(win_pos.x, win_pos.y);
const Rect monitor_rect = virtual_rect.GetMonitorRect();
const Point offset_to_column1(kColumn0Width, 0);

const Rect adjusted_win_geometry =
Expand Down

0 comments on commit 37424fc

Please sign in to comment.