Commit d95c3ea0 authored by Yuanle Song's avatar Yuanle Song
Browse files

v1.3.0 support multiple monitor setup.

zero-panel should show in the monitor that emacs runs.
move_window() is updated to support multiple monitor setup.
parent 7caf3efc
Loading
Loading
Loading
Loading
+1 −1
Original line number Diff line number Diff line
# -*- mode: conf -*-
project('zero-panel', 'c',
  version: '1.2.3',
  version: '1.3.0',
  license: 'EPL-2.0',
  meson_version: '>=0.46.0',
  default_options: [
+151 −1
Original line number Diff line number Diff line
* COMMENT -*- mode: org -*-
#+Date: 2019-09-02
Time-stamp: <2019-09-03>
Time-stamp: <2020-06-03>
#+STARTUP: content
* notes                                                               :entry:
** 2020-06-03 how to test dual monitor support
- dual display test: when user type in emacs frame in a
  display, zero-panel should appear in the same display.

- some elisp to test dual monitor support in dual 1920x1080 monitor.

  (zero-input-panel-quit)
  (zero-input-panel-move 0 0)
  (zero-input-panel-move 900 0)
  (zero-input-panel-move 900 500)
  (zero-input-panel-move 3208 884)
  (zero-input-panel-show)
  (zero-input-panel-hide)

** 2020-06-03 how to run with debug log when developing new features?
- kill existing zero-panel process
  (zero-input-panel-quit)

- compile program using meson.
  in emacs, just press F8.

- run program:

  cd build/
  G_MESSAGES_DEBUG=all ./zero-panel

* later                                                               :entry:
** 2019-09-03 bug: panel window should not get focus in GNOME 3 on Wayland.
currently panel keeps flashing when typing in this env.
@@ -30,6 +56,130 @@ is it supported by zero-el?
** 2019-09-02 remove black bg in round corner. should be transparent.
is it because I don't have a compositor that support alpha?
* done                                                                :entry:
** 2020-06-03 support dual monitor
- bug: 双显示器 zero-panel panel 没有显示到光标位置。而是在另一个屏幕右侧边缘。
  而且高度是对的。
- 先看 zero-el 发送给 zero-panel 的坐标是否正确。是否包含 monitor 信息。
  然后看 zero-panel 的响应是否正确。
- zero-input-show-candidates

  (zero-input-get-point-position)(3208 884)
  这个没问题。

  单块屏幕分辨率是 1920x1080
  这个返回的坐标是考虑了显示器相对位置的坐标。

  (zero-input-panel-move 3208 884)
  (zero-input-panel-show)

  // 这个有问题。move的时候没有考虑多显示器的情况。

  check dbus service server side.

  ~/c/zero-panel/server.c

  static void
  move_window(gint x, gint y, AppData *appdata)

  display = gdk_display_get_default();
  monitor = gdk_display_get_monitor_at_window(display, window);

  this is wrong.
  we should get the monitor for emacs window, not zero-panel window.
  we should move the zero-panel window to emacs window's monitor.
  then move the window to specific position.

  TODO add test case, dual display test: when user type in emacs frame in a
  display, zero-panel should appear in the same display.

- how to do that?

  we should get the monitor for emacs window, not zero-panel window.
  we should move the zero-panel window to emacs window's monitor.
  then move the window to specific position on that monitor.

  WONTFIX is there an API to move the window to screen position instead of
  monitor position? if there is, maybe just use that API instead? still need
  to consider borders though.

- problems
  - how to get the monitor ID where the emacs frame is running on?
    pass the monitor ID in hints.

    check elisp doc.
    Info: (elisp) Basic Parameters

    ‘display’
     The display on which to open this frame.  It should be a string of
     the form ‘HOST:DPY.SCREEN’, just like the ‘DISPLAY’ environment
     variable.  *Note Multiple Terminals::, for more details about
     display names.

    (frame-parameter nil 'display)":0"
    this is always ":0". it's X server display. not physical display.

    search: emacs get frame's display number in dual monitor setup

    (display-monitor-attributes-list)

    when there are two frames, one on each display, this is the result:
    #+BEGIN_SRC elisp
      (((name . "DP-0")
        (geometry 1920 0 1920 1080)
        (workarea 1920 0 1920 1080)
        (mm-size 527 296)
        (frames #<frame operational|zero-panel 0x1108c30>)
        (source . "Gdk"))
       ((name . "HDMI-0")
        (geometry 0 0 1920 1080)
        (workarea 0 0 1920 1080)
        (mm-size 531 299)
        (frames #<frame operational|zero-panel 0x583dce0>)
        (source . "Gdk")))
    #+END_SRC

    when there is only one frame on DP-0 display:
    (display-monitor-attributes-list)
    #+BEGIN_SRC elisp
      (((name . "DP-0")
        (geometry 1920 0 1920 1080)
        (workarea 1920 0 1920 1080)
        (mm-size 527 296)
        (frames #<frame emacs25@ryzen5 0x1108c30>)
        (source . "Gdk"))
       ((name . "HDMI-0")
        (geometry 0 0 1920 1080)
        (workarea 0 0 1920 1080)
        (mm-size 531 299)
        (frames)
        (source . "Gdk")))
    #+END_SRC

    可以根据坐标计算出当前frame在哪个display。
    geometry x y width height
    x y 可以看出display的相对位置。

    try use gdk_display_get_monitor_at_point ()
    http://localdocs.emacsos.com/gdk3/GdkDisplay.html#gdk-display-get-monitor-at-point

  - how to move window to the correct monitor?

    try just move to the coordinate.
    correct formula to calculate overflow.

    #+BEGIN_SRC sh
      (zero-panel:57769): DEBUG: on_handle_show_candidates() preedit_str=h
      (zero-panel:57769): DEBUG: show_candidates()
      (zero-panel:57769): DEBUG: move_window x=2881 y=869
      (zero-panel:57769): DEBUG: 2 monitors belong to :0
      (zero-panel:57769): DEBUG: screen size: x=1920 y=0 width=1920 height=1080
      (zero-panel:57769): DEBUG: window size:width=120 height=284
      (zero-panel:57769): DEBUG: set newx=1920-120=1800
      (zero-panel:57769): DEBUG: set newy=1080-284=796
    #+END_SRC

    it works.

** 2019-09-02 should I add README in deb file? where to install it to?
/usr/share/doc/zero-panel/README

+21 −12
Original line number Diff line number Diff line
@@ -200,17 +200,24 @@ move_window(gint x, gint y, AppData *appdata)
	/* user passed in coordinate is honored on best effort. */
	/* do some calculation, try not to let window flow out of screen. */
	GdkDisplay *display = NULL;
	GdkWindow *window = NULL;
	GdkMonitor *monitor = NULL;
	GdkRectangle geometry = {0};
#ifdef DEBUG
	int n;
#endif

	g_debug("move_window x=%d y=%d", x, y);

	/* get screen size */
	window = gtk_widget_get_window(appdata->window);
	display = gdk_display_get_default();
	monitor = gdk_display_get_monitor_at_window(display, window);
#ifdef DEBUG
	n = gdk_display_get_n_monitors(display);
	g_debug("%d monitors belong to %s", n, gdk_display_get_name(display));
#endif
	monitor = gdk_display_get_monitor_at_point(display, x, y);
	gdk_monitor_get_geometry(monitor, &geometry);
	/* now screen size is in geometry.[width|height] */
	g_debug("screen size: x=%d y=%d width=%d height=%d",
	/* now monitor size is in geometry.[width|height] */
	g_debug("monitor size: x=%d y=%d width=%d height=%d",
		geometry.x, geometry.y, geometry.width, geometry.height);

	/* this window's size */
@@ -219,16 +226,18 @@ move_window(gint x, gint y, AppData *appdata)
	gtk_window_get_size(GTK_WINDOW(appdata->window), &width, &height);
	g_debug("window size:width=%d height=%d", width, height);

	/* try not to let window flow out of screen. */
	/* try not to let window flow out of monitor. */
	gint newx = x;
	gint newy = y;
	if (x + width > geometry.width) {
		newx = geometry.width - width;
		g_debug("set newx=%d-%d=%d", geometry.width, width, newx);
	}
	if (y + height > geometry.height) {
		newy = geometry.height - height;
		g_debug("set newy=%d-%d=%d", geometry.height, height, newy);
	if (x - geometry.x + width > geometry.width) {
		newx = geometry.x + geometry.width - width;
		g_debug("set newx=%d+%d-%d=%d",
			geometry.x, geometry.width, width, newx);
	}
	if (y - geometry.y + height > geometry.height) {
		newy = geometry.y + geometry.height - height;
		g_debug("set newy=%d+%d-%d=%d",
			geometry.y, geometry.height, height, newy);
	}
	if (x < geometry.x) {
		newx = geometry.x;