diff options
| author | Yuuki Harano | 2019-07-07 02:24:14 +0900 |
|---|---|---|
| committer | Jeff Walsh | 2020-11-22 14:46:55 +1100 |
| commit | fbba846ee8d63304385b59e8f6a553398b533345 (patch) | |
| tree | dbb8d888648ff228b5b222865c78799ae9adbcca /src | |
| parent | 85441c96d74f82ca368b950aa0f5334297bf4fa0 (diff) | |
| download | emacs-fbba846ee8d63304385b59e8f6a553398b533345.tar.gz emacs-fbba846ee8d63304385b59e8f6a553398b533345.zip | |
Addframe highlighting support
* ../src/pgtkterm.c:
(pgtk_focus_frame, set_opacity_recursively, x_set_frame_alpha)
(frame_highlight, frame_unhighlight, pgtk_frame_rehighlight)
(XTframe_rehighlight, x_new_focus_frame, pgtk_create_terminal):
frame の highlight に対応。
とりあえず opacity のみ対応。
Diffstat (limited to 'src')
| -rw-r--r-- | src/pgtkterm.c | 316 | ||||
| -rw-r--r-- | src/pgtkterm.h | 1 |
2 files changed, 187 insertions, 130 deletions
diff --git a/src/pgtkterm.c b/src/pgtkterm.c index fb2520614f2..1c2f0c96487 100644 --- a/src/pgtkterm.c +++ b/src/pgtkterm.c | |||
| @@ -4351,6 +4351,190 @@ pgtk_free_pixmap (struct frame *_f, Emacs_Pixmap pixmap) | |||
| 4351 | } | 4351 | } |
| 4352 | } | 4352 | } |
| 4353 | 4353 | ||
| 4354 | void | ||
| 4355 | pgtk_focus_frame (struct frame *f, bool noactivate) | ||
| 4356 | { | ||
| 4357 | struct pgtk_display_info *dpyinfo = FRAME_DISPLAY_INFO (f); | ||
| 4358 | |||
| 4359 | GtkWidget *wid = FRAME_GTK_OUTER_WIDGET(f); | ||
| 4360 | |||
| 4361 | if (dpyinfo->x_focus_frame != f) | ||
| 4362 | { | ||
| 4363 | block_input (); | ||
| 4364 | gtk_window_present (GTK_WINDOW (wid)); | ||
| 4365 | unblock_input (); | ||
| 4366 | } | ||
| 4367 | } | ||
| 4368 | |||
| 4369 | |||
| 4370 | static void set_opacity_recursively (GtkWidget *w, gpointer data) | ||
| 4371 | { | ||
| 4372 | gtk_widget_set_opacity (w, *(double *) data); | ||
| 4373 | if (GTK_IS_CONTAINER (w)) | ||
| 4374 | gtk_container_foreach (GTK_CONTAINER (w), set_opacity_recursively, data); | ||
| 4375 | } | ||
| 4376 | |||
| 4377 | static void | ||
| 4378 | x_set_frame_alpha (struct frame *f) | ||
| 4379 | { | ||
| 4380 | struct pgtk_display_info *dpyinfo = FRAME_DISPLAY_INFO (f); | ||
| 4381 | double alpha = 1.0; | ||
| 4382 | double alpha_min = 1.0; | ||
| 4383 | |||
| 4384 | if (dpyinfo->highlight_frame == f) | ||
| 4385 | alpha = f->alpha[0]; | ||
| 4386 | else | ||
| 4387 | alpha = f->alpha[1]; | ||
| 4388 | |||
| 4389 | if (alpha < 0.0) | ||
| 4390 | return; | ||
| 4391 | |||
| 4392 | if (FLOATP (Vframe_alpha_lower_limit)) | ||
| 4393 | alpha_min = XFLOAT_DATA (Vframe_alpha_lower_limit); | ||
| 4394 | else if (FIXNUMP (Vframe_alpha_lower_limit)) | ||
| 4395 | alpha_min = (XFIXNUM (Vframe_alpha_lower_limit)) / 100.0; | ||
| 4396 | |||
| 4397 | if (alpha > 1.0) | ||
| 4398 | alpha = 1.0; | ||
| 4399 | else if (alpha < alpha_min && alpha_min <= 1.0) | ||
| 4400 | alpha = alpha_min; | ||
| 4401 | |||
| 4402 | #if 0 | ||
| 4403 | /* If there is a parent from the window manager, put the property there | ||
| 4404 | also, to work around broken window managers that fail to do that. | ||
| 4405 | Do this unconditionally as this function is called on reparent when | ||
| 4406 | alpha has not changed on the frame. */ | ||
| 4407 | |||
| 4408 | if (!FRAME_PARENT_FRAME (f)) | ||
| 4409 | { | ||
| 4410 | Window parent = x_find_topmost_parent (f); | ||
| 4411 | if (parent != None) | ||
| 4412 | XChangeProperty (dpy, parent, dpyinfo->Xatom_net_wm_window_opacity, | ||
| 4413 | XA_CARDINAL, 32, PropModeReplace, | ||
| 4414 | (unsigned char *) &opac, 1); | ||
| 4415 | } | ||
| 4416 | #endif | ||
| 4417 | |||
| 4418 | set_opacity_recursively (FRAME_GTK_OUTER_WIDGET (f), &alpha); | ||
| 4419 | /* without this, blending mode is strange on wayland. */ | ||
| 4420 | gtk_widget_queue_resize_no_redraw (FRAME_GTK_OUTER_WIDGET (f)); | ||
| 4421 | } | ||
| 4422 | |||
| 4423 | static void | ||
| 4424 | frame_highlight (struct frame *f) | ||
| 4425 | { | ||
| 4426 | /* We used to only do this if Vx_no_window_manager was non-nil, but | ||
| 4427 | the ICCCM (section 4.1.6) says that the window's border pixmap | ||
| 4428 | and border pixel are window attributes which are "private to the | ||
| 4429 | client", so we can always change it to whatever we want. */ | ||
| 4430 | block_input (); | ||
| 4431 | /* I recently started to get errors in this XSetWindowBorder, depending on | ||
| 4432 | the window-manager in use, tho something more is at play since I've been | ||
| 4433 | using that same window-manager binary for ever. Let's not crash just | ||
| 4434 | because of this (bug#9310). */ | ||
| 4435 | #if 0 | ||
| 4436 | x_catch_errors (FRAME_X_DISPLAY (f)); | ||
| 4437 | XSetWindowBorder (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), | ||
| 4438 | FRAME_X_OUTPUT(f)->border_pixel); | ||
| 4439 | x_uncatch_errors (); | ||
| 4440 | #endif | ||
| 4441 | unblock_input (); | ||
| 4442 | gui_update_cursor (f, true); | ||
| 4443 | x_set_frame_alpha (f); | ||
| 4444 | } | ||
| 4445 | |||
| 4446 | static void | ||
| 4447 | frame_unhighlight (struct frame *f) | ||
| 4448 | { | ||
| 4449 | /* We used to only do this if Vx_no_window_manager was non-nil, but | ||
| 4450 | the ICCCM (section 4.1.6) says that the window's border pixmap | ||
| 4451 | and border pixel are window attributes which are "private to the | ||
| 4452 | client", so we can always change it to whatever we want. */ | ||
| 4453 | block_input (); | ||
| 4454 | /* Same as above for XSetWindowBorder (bug#9310). */ | ||
| 4455 | #if 0 | ||
| 4456 | x_catch_errors (FRAME_X_DISPLAY (f)); | ||
| 4457 | XSetWindowBorderPixmap (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), | ||
| 4458 | FRAME_X_OUTPUT(f)->border_tile); | ||
| 4459 | x_uncatch_errors (); | ||
| 4460 | #endif | ||
| 4461 | unblock_input (); | ||
| 4462 | gui_update_cursor (f, true); | ||
| 4463 | x_set_frame_alpha (f); | ||
| 4464 | } | ||
| 4465 | |||
| 4466 | |||
| 4467 | static void | ||
| 4468 | pgtk_frame_rehighlight (struct pgtk_display_info *dpyinfo) | ||
| 4469 | { | ||
| 4470 | struct frame *old_highlight = dpyinfo->highlight_frame; | ||
| 4471 | |||
| 4472 | if (dpyinfo->x_focus_frame) | ||
| 4473 | { | ||
| 4474 | dpyinfo->highlight_frame | ||
| 4475 | = ((FRAMEP (FRAME_FOCUS_FRAME (dpyinfo->x_focus_frame))) | ||
| 4476 | ? XFRAME (FRAME_FOCUS_FRAME (dpyinfo->x_focus_frame)) | ||
| 4477 | : dpyinfo->x_focus_frame); | ||
| 4478 | if (! FRAME_LIVE_P (dpyinfo->highlight_frame)) | ||
| 4479 | { | ||
| 4480 | fset_focus_frame (dpyinfo->x_focus_frame, Qnil); | ||
| 4481 | dpyinfo->highlight_frame = dpyinfo->x_focus_frame; | ||
| 4482 | } | ||
| 4483 | } | ||
| 4484 | else | ||
| 4485 | dpyinfo->highlight_frame = 0; | ||
| 4486 | |||
| 4487 | if (dpyinfo->highlight_frame != old_highlight) | ||
| 4488 | { | ||
| 4489 | if (old_highlight) | ||
| 4490 | frame_unhighlight (old_highlight); | ||
| 4491 | if (dpyinfo->highlight_frame) | ||
| 4492 | frame_highlight (dpyinfo->highlight_frame); | ||
| 4493 | } | ||
| 4494 | } | ||
| 4495 | |||
| 4496 | /* The focus has changed, or we have redirected a frame's focus to | ||
| 4497 | another frame (this happens when a frame uses a surrogate | ||
| 4498 | mini-buffer frame). Shift the highlight as appropriate. | ||
| 4499 | |||
| 4500 | The FRAME argument doesn't necessarily have anything to do with which | ||
| 4501 | frame is being highlighted or un-highlighted; we only use it to find | ||
| 4502 | the appropriate X display info. */ | ||
| 4503 | |||
| 4504 | static void | ||
| 4505 | XTframe_rehighlight (struct frame *frame) | ||
| 4506 | { | ||
| 4507 | pgtk_frame_rehighlight (FRAME_DISPLAY_INFO (frame)); | ||
| 4508 | } | ||
| 4509 | |||
| 4510 | /* The focus has changed. Update the frames as necessary to reflect | ||
| 4511 | the new situation. Note that we can't change the selected frame | ||
| 4512 | here, because the Lisp code we are interrupting might become confused. | ||
| 4513 | Each event gets marked with the frame in which it occurred, so the | ||
| 4514 | Lisp code can tell when the switch took place by examining the events. */ | ||
| 4515 | |||
| 4516 | static void | ||
| 4517 | x_new_focus_frame (struct pgtk_display_info *dpyinfo, struct frame *frame) | ||
| 4518 | { | ||
| 4519 | struct frame *old_focus = dpyinfo->x_focus_frame; | ||
| 4520 | /* doesn't work on wayland */ | ||
| 4521 | |||
| 4522 | if (frame != dpyinfo->x_focus_frame) | ||
| 4523 | { | ||
| 4524 | /* Set this before calling other routines, so that they see | ||
| 4525 | the correct value of x_focus_frame. */ | ||
| 4526 | dpyinfo->x_focus_frame = frame; | ||
| 4527 | |||
| 4528 | if (old_focus && old_focus->auto_lower) | ||
| 4529 | gdk_window_lower (gtk_widget_get_window (FRAME_GTK_OUTER_WIDGET (old_focus))); | ||
| 4530 | |||
| 4531 | if (dpyinfo->x_focus_frame && dpyinfo->x_focus_frame->auto_raise) | ||
| 4532 | gdk_window_raise (gtk_widget_get_window (FRAME_GTK_OUTER_WIDGET (dpyinfo->x_focus_frame))); | ||
| 4533 | } | ||
| 4534 | |||
| 4535 | pgtk_frame_rehighlight (dpyinfo); | ||
| 4536 | } | ||
| 4537 | |||
| 4354 | static struct terminal * | 4538 | static struct terminal * |
| 4355 | pgtk_create_terminal (struct pgtk_display_info *dpyinfo) | 4539 | pgtk_create_terminal (struct pgtk_display_info *dpyinfo) |
| 4356 | /* -------------------------------------------------------------------------- | 4540 | /* -------------------------------------------------------------------------- |
| @@ -4371,7 +4555,7 @@ pgtk_create_terminal (struct pgtk_display_info *dpyinfo) | |||
| 4371 | terminal->read_socket_hook = pgtk_read_socket; | 4555 | terminal->read_socket_hook = pgtk_read_socket; |
| 4372 | // terminal->frame_up_to_date_hook = pgtk_frame_up_to_date; | 4556 | // terminal->frame_up_to_date_hook = pgtk_frame_up_to_date; |
| 4373 | terminal->mouse_position_hook = pgtk_mouse_position; | 4557 | terminal->mouse_position_hook = pgtk_mouse_position; |
| 4374 | // terminal->frame_rehighlight_hook = pgtk_frame_rehighlight; | 4558 | terminal->frame_rehighlight_hook = XTframe_rehighlight; |
| 4375 | // terminal->frame_raise_lower_hook = pgtk_frame_raise_lower; | 4559 | // terminal->frame_raise_lower_hook = pgtk_frame_raise_lower; |
| 4376 | terminal->frame_visible_invisible_hook = pgtk_make_frame_visible_invisible; | 4560 | terminal->frame_visible_invisible_hook = pgtk_make_frame_visible_invisible; |
| 4377 | terminal->fullscreen_hook = pgtk_fullscreen_hook; | 4561 | terminal->fullscreen_hook = pgtk_fullscreen_hook; |
| @@ -5095,132 +5279,6 @@ static gboolean delete_event(GtkWidget *widget, GdkEvent *event, gpointer *user_ | |||
| 5095 | return TRUE; | 5279 | return TRUE; |
| 5096 | } | 5280 | } |
| 5097 | 5281 | ||
| 5098 | void | ||
| 5099 | pgtk_focus_frame (struct frame *f, bool noactivate) | ||
| 5100 | { | ||
| 5101 | struct pgtk_display_info *dpyinfo = FRAME_DISPLAY_INFO (f); | ||
| 5102 | |||
| 5103 | GtkWidget *wid = FRAME_GTK_OUTER_WIDGET(f); | ||
| 5104 | |||
| 5105 | if (dpyinfo->x_focus_frame != f) | ||
| 5106 | { | ||
| 5107 | block_input (); | ||
| 5108 | gtk_window_present (GTK_WINDOW (wid)); | ||
| 5109 | unblock_input (); | ||
| 5110 | } | ||
| 5111 | } | ||
| 5112 | |||
| 5113 | |||
| 5114 | static void | ||
| 5115 | frame_highlight (struct frame *f) | ||
| 5116 | { | ||
| 5117 | /* We used to only do this if Vx_no_window_manager was non-nil, but | ||
| 5118 | the ICCCM (section 4.1.6) says that the window's border pixmap | ||
| 5119 | and border pixel are window attributes which are "private to the | ||
| 5120 | client", so we can always change it to whatever we want. */ | ||
| 5121 | block_input (); | ||
| 5122 | /* I recently started to get errors in this XSetWindowBorder, depending on | ||
| 5123 | the window-manager in use, tho something more is at play since I've been | ||
| 5124 | using that same window-manager binary for ever. Let's not crash just | ||
| 5125 | because of this (bug#9310). */ | ||
| 5126 | #if 0 | ||
| 5127 | x_catch_errors (FRAME_X_DISPLAY (f)); | ||
| 5128 | XSetWindowBorder (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), | ||
| 5129 | FRAME_X_OUTPUT(f)->border_pixel); | ||
| 5130 | x_uncatch_errors (); | ||
| 5131 | #endif | ||
| 5132 | unblock_input (); | ||
| 5133 | gui_update_cursor (f, true); | ||
| 5134 | #if 0 | ||
| 5135 | x_set_frame_alpha (f); | ||
| 5136 | #endif | ||
| 5137 | } | ||
| 5138 | |||
| 5139 | static void | ||
| 5140 | frame_unhighlight (struct frame *f) | ||
| 5141 | { | ||
| 5142 | /* We used to only do this if Vx_no_window_manager was non-nil, but | ||
| 5143 | the ICCCM (section 4.1.6) says that the window's border pixmap | ||
| 5144 | and border pixel are window attributes which are "private to the | ||
| 5145 | client", so we can always change it to whatever we want. */ | ||
| 5146 | block_input (); | ||
| 5147 | /* Same as above for XSetWindowBorder (bug#9310). */ | ||
| 5148 | #if 0 | ||
| 5149 | x_catch_errors (FRAME_X_DISPLAY (f)); | ||
| 5150 | XSetWindowBorderPixmap (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), | ||
| 5151 | FRAME_X_OUTPUT(f)->border_tile); | ||
| 5152 | x_uncatch_errors (); | ||
| 5153 | #endif | ||
| 5154 | unblock_input (); | ||
| 5155 | gui_update_cursor (f, true); | ||
| 5156 | #if 0 | ||
| 5157 | x_set_frame_alpha (f); | ||
| 5158 | #endif | ||
| 5159 | } | ||
| 5160 | |||
| 5161 | |||
| 5162 | static void | ||
| 5163 | x_frame_rehighlight (struct pgtk_display_info *dpyinfo) | ||
| 5164 | { | ||
| 5165 | struct frame *old_highlight = dpyinfo->highlight_frame; | ||
| 5166 | |||
| 5167 | if (dpyinfo->x_focus_frame) | ||
| 5168 | { | ||
| 5169 | dpyinfo->highlight_frame | ||
| 5170 | = ((FRAMEP (FRAME_FOCUS_FRAME (dpyinfo->x_focus_frame))) | ||
| 5171 | ? XFRAME (FRAME_FOCUS_FRAME (dpyinfo->x_focus_frame)) | ||
| 5172 | : dpyinfo->x_focus_frame); | ||
| 5173 | if (! FRAME_LIVE_P (dpyinfo->highlight_frame)) | ||
| 5174 | { | ||
| 5175 | fset_focus_frame (dpyinfo->x_focus_frame, Qnil); | ||
| 5176 | dpyinfo->highlight_frame = dpyinfo->x_focus_frame; | ||
| 5177 | } | ||
| 5178 | } | ||
| 5179 | else | ||
| 5180 | dpyinfo->highlight_frame = 0; | ||
| 5181 | |||
| 5182 | if (dpyinfo->highlight_frame != old_highlight) | ||
| 5183 | { | ||
| 5184 | if (old_highlight) | ||
| 5185 | frame_unhighlight (old_highlight); | ||
| 5186 | if (dpyinfo->highlight_frame) | ||
| 5187 | frame_highlight (dpyinfo->highlight_frame); | ||
| 5188 | } | ||
| 5189 | } | ||
| 5190 | |||
| 5191 | /* The focus has changed. Update the frames as necessary to reflect | ||
| 5192 | the new situation. Note that we can't change the selected frame | ||
| 5193 | here, because the Lisp code we are interrupting might become confused. | ||
| 5194 | Each event gets marked with the frame in which it occurred, so the | ||
| 5195 | Lisp code can tell when the switch took place by examining the events. */ | ||
| 5196 | |||
| 5197 | static void | ||
| 5198 | x_new_focus_frame (struct pgtk_display_info *dpyinfo, struct frame *frame) | ||
| 5199 | { | ||
| 5200 | struct frame *old_focus = dpyinfo->x_focus_frame; | ||
| 5201 | |||
| 5202 | if (frame != dpyinfo->x_focus_frame) | ||
| 5203 | { | ||
| 5204 | /* Set this before calling other routines, so that they see | ||
| 5205 | the correct value of x_focus_frame. */ | ||
| 5206 | dpyinfo->x_focus_frame = frame; | ||
| 5207 | |||
| 5208 | #if 0 | ||
| 5209 | if (old_focus && old_focus->auto_lower) | ||
| 5210 | x_lower_frame (old_focus); | ||
| 5211 | #endif | ||
| 5212 | |||
| 5213 | #if 0 | ||
| 5214 | if (dpyinfo->x_focus_frame && dpyinfo->x_focus_frame->auto_raise) | ||
| 5215 | dpyinfo->x_pending_autoraise_frame = dpyinfo->x_focus_frame; | ||
| 5216 | else | ||
| 5217 | dpyinfo->x_pending_autoraise_frame = NULL; | ||
| 5218 | #endif | ||
| 5219 | } | ||
| 5220 | |||
| 5221 | x_frame_rehighlight (dpyinfo); | ||
| 5222 | } | ||
| 5223 | |||
| 5224 | /* The focus may have changed. Figure out if it is a real focus change, | 5282 | /* The focus may have changed. Figure out if it is a real focus change, |
| 5225 | by checking both FocusIn/Out and Enter/LeaveNotify events. | 5283 | by checking both FocusIn/Out and Enter/LeaveNotify events. |
| 5226 | 5284 | ||
| @@ -5269,10 +5327,8 @@ x_focus_changed (gboolean is_enter, int state, struct pgtk_display_info *dpyinfo | |||
| 5269 | XSETFRAME (bufp->ie.frame_or_window, frame); | 5327 | XSETFRAME (bufp->ie.frame_or_window, frame); |
| 5270 | } | 5328 | } |
| 5271 | 5329 | ||
| 5272 | #if 0 | ||
| 5273 | if (frame->pointer_invisible) | 5330 | if (frame->pointer_invisible) |
| 5274 | XTtoggle_invisible_pointer (frame, false); | 5331 | XTtoggle_invisible_pointer (frame, false); |
| 5275 | #endif | ||
| 5276 | } | 5332 | } |
| 5277 | } | 5333 | } |
| 5278 | 5334 | ||
diff --git a/src/pgtkterm.h b/src/pgtkterm.h index 4b585079b86..91990b203bd 100644 --- a/src/pgtkterm.h +++ b/src/pgtkterm.h | |||
| @@ -579,5 +579,6 @@ extern void pgtk_set_scroll_bar_default_width (struct frame *f); | |||
| 579 | extern void pgtk_set_scroll_bar_default_height (struct frame *f); | 579 | extern void pgtk_set_scroll_bar_default_height (struct frame *f); |
| 580 | extern Lisp_Object x_get_focus_frame (struct frame *frame); | 580 | extern Lisp_Object x_get_focus_frame (struct frame *frame); |
| 581 | 581 | ||
| 582 | extern void pgtk_frame_rehighlight (struct pgtk_display_info *dpyinfo); | ||
| 582 | 583 | ||
| 583 | #endif /* HAVE_PGTK */ | 584 | #endif /* HAVE_PGTK */ |