[MPlayer-dev-eng] [PATCH] double click to switch to full screen in GUI

Diego Biurrun diego at biurrun.de
Mon Oct 2 00:23:22 CEST 2006


On Fri, Sep 29, 2006 at 06:16:56PM +0200, Reimar Döffinger wrote:
> On Thu, Sep 14, 2006 at 11:11:07PM +0200, laurent wozniak wrote:
> >   gtkInit();
> > +// --- initialize some input constants 
> > + g_object_get ( G_OBJECT ( gtk_settings_get_default() ), 
> > +    "gtk-double-click-time", &double_click_time, NULL );
> > + mp_input_set_double_click_time(double_click_time);
> 
> I don't care much, but it should be tested if this works with GTK1

Apparently it does not, I get linking errors 'undefined reference to
gtk_settings_get_default'.  Some sort of solution is needed.  This part
of the code can be dropped, protected by #ifdef or support for GTK 1.x
dropped.

> > @@ -305,6 +307,7 @@
> >  
> >  static mp_cmd_bind_t def_cmd_binds[] = {
> >  
> > +  { {  MOUSE_BTN0_DBL, 0 }, "vo_fullscreen" },
> 
> I'd prefer it not to be bound by default.

I strongly disagree.  Pretty much every player goes into fullscreen on
doubleclick.  I'm not aware of any that doesn't...

> > +// Mouse button double click time
> > +// Default value may be overridden during the gui initialization 
> > +static unsigned int double_click_time = 300;
> > +
> 
> probably should be a command line option.

Oh dear, another one?

> > +  // When binding a command to a mouse button double click,
> > +  // if the corresponding single click is not bound,
> > +  // bind it to the command which does nothing:
> > +  // Avoid logging command not found on the first click of the double click.
> > +  for(j = 0 ; (key = keys[j]) != 0 ; j++) {
> > +    if (MOUSE_BTN0_DBL <= key && key <= MOUSE_BTN_LAST_DBL) {
> > +      key = MOUSE_BTN0 + key - MOUSE_BTN0_DBL;
> > +      other_cmd = mp_input_find_bind_for_key(1, &key);
> > +      if (other_cmd == NULL) {
> > +        int other_cmd_keys[2];      	
> > +        other_cmd_keys[0] = key;
> > +        other_cmd_keys[1] = 0;      	
> > +        mp_input_bind_keys(other_cmd_keys, MP_CMD_TXT_NO_COMMAND);
> > +      }
> > +    }
> > +  }
> > +
> 
> I find the (IMHO doubtful since possibly confusing) convenience of not having
> to add a no_command keybind not worth even that few lines of code.

I'm a bit sceptical myself here, but the convenience is real ..

> > +void mplayer_put_key(int code) {
> > +  unsigned int now;
> > +  int btn;
> > +  int ignore;
> > +  
> > +  ignore = code & MP_VETOED_KEY;
> > +  code &= ~MP_VETOED_KEY;
> > +
> > +  // Check mouse button press event
> > +  if ((MOUSE_BTN0 | MP_KEY_DOWN) <= code && code <= (MOUSE_BTN_LAST | MP_KEY_DOWN)) {  
> > +    btn = code - (MOUSE_BTN0 | MP_KEY_DOWN);    
> 
> trailing whitespace...

I've cleaned up the patch a bit, removing trailing whitespace,
reformatting code to match the file it's in and improving some comments.
I'm attaching the patch so we can use this as the new baseline for
discussions.

Diego
-------------- next part --------------
Index: Gui/interface.c
===================================================================
--- Gui/interface.c	(revision 19814)
+++ Gui/interface.c	(working copy)
@@ -202,6 +202,7 @@
 							    
 void guiInit( void )
 {
+ gint doubleclick_time;
  int i;
 
  memset( &guiIntfStruct,0,sizeof( guiIntfStruct ) );
@@ -217,6 +218,10 @@
  if ( autosync && autosync != gtkAutoSync ) { gtkAutoSyncOn=1; gtkAutoSync=autosync; }
    
  gtkInit();
+// --- initialize some input constants
+ g_object_get ( G_OBJECT ( gtk_settings_get_default() ),
+    "gtk-double-click-time", &doubleclick_time, NULL );
+ mp_input_set_doubleclick_time(doubleclick_time);
 // --- initialize X 
  wsXInit( (void *)mDisplay );
 // --- load skin
Index: Gui/mplayer/sw.c
===================================================================
--- Gui/mplayer/sw.c	(revision 19814)
+++ Gui/mplayer/sw.c	(working copy)
@@ -12,6 +12,11 @@
 #include "../help_mp.h"
 #include "widgets.h"
 
+#include "../input/input.h"
+#include "../input/mouse.h"
+
+extern void mplayer_put_key(int code);
+
 int             mplSubRender = 0;
 int             SubVisible = 0;
 
@@ -43,10 +48,17 @@
  static int mplSubMoved = 0;
  static int msButton = 0;
 
+ int btn, veto;
+
  mplPBShow( X,Y );
+
+ /* Activate mouse event veto by default. */
+ veto = MP_VETOED_KEY;
 
  switch( Button )
   {
+   case wsPRMouseButton:
+          break;
    case wsRRMouseButton:
           gtkShow( evShowPopUpMenu,NULL );
           break;
@@ -88,5 +101,18 @@
           msButton=0;
           mplSubMoved=0;
           break;
+// ---
+   default:
+          /* Mouse event not handled, remove veto. */
+          veto = 0;
   }
+
+  if ( wsP0MouseButton <= Button && Button <= wsPLastMouseButton ) {
+    btn = Button - wsP0MouseButton;
+    mplayer_put_key((MOUSE_BTN0 + btn) | veto | MP_KEY_DOWN);
+  }
+  else if ( wsR0MouseButton <= Button && Button <= wsRLastMouseButton ) {
+    btn = Button - wsR0MouseButton;
+    mplayer_put_key((MOUSE_BTN0 + btn) | veto);
+  }
 }
Index: Gui/wm/ws.h
===================================================================
--- Gui/wm/ws.h	(revision 19814)
+++ Gui/wm/ws.h	(working copy)
@@ -29,11 +29,15 @@
 #define  wsPRMouseButton 3
 #define  wsP4MouseButton 4
 #define  wsP5MouseButton 5
-#define  wsRLMouseButton 1 + 128
-#define  wsRMMouseButton 2 + 128
-#define  wsRRMouseButton 3 + 128
-#define  wsR4MouseButton 4 + 128
-#define  wsR5MouseButton 5 + 128
+#define  wsP0MouseButton wsPLMouseButton
+#define  wsPLastMouseButton 10
+#define  wsRLMouseButton (1 + 128)
+#define  wsRMMouseButton (2 + 128)
+#define  wsRRMouseButton (3 + 128)
+#define  wsR4MouseButton (4 + 128)
+#define  wsR5MouseButton (5 + 128)
+#define  wsR0MouseButton wsRLMouseButton
+#define  wsRLastMouseButton (10 + 128)
 #define  wsEnterWindow   253
 #define  wsLeaveWindow   254
 #define  wsMoveMouse     255
Index: fifo.c
===================================================================
--- fifo.c	(revision 19814)
+++ fifo.c	(working copy)
@@ -25,7 +25,7 @@
   set_nonblock_flag(temp[1]);
 }
 
-void mplayer_put_key(int code){
+void mplayer_put_key_internal(int code){
 
     if( write(keyb_fifo_put,&code,4) != 4 ){
         mp_msg(MSGT_INPUT,MSGL_ERR,"*** key event dropped (FIFO is full) ***\n");
@@ -39,8 +39,8 @@
 static int key_fifo_read=0;
 static int key_fifo_write=0;
 
-void mplayer_put_key(int code){
-//  printf("mplayer_put_key(%d)\n",code);
+void mplayer_put_key_internal(int code){
+//  printf("mplayer_put_key_internal(%d)\n",code);
   if (key_fifo_data == NULL)
     key_fifo_data = malloc(key_fifo_size * sizeof(int));
   if(((key_fifo_write+1)%key_fifo_size)==key_fifo_read) return; // FIFO FULL!!
Index: input/input.c
===================================================================
--- input/input.c	(revision 19814)
+++ input/input.c	(working copy)
@@ -35,6 +35,8 @@
 #include <lirc/lircc.h>
 #endif
 
+#define MP_CMD_TXT_NO_COMMAND "no_command"
+
 /// This array defines all known commands.
 /// The first field is an id used to recognize the command without too many strcmp.
 /// The second is obviously the command name.
@@ -305,6 +307,7 @@
 
 static mp_cmd_bind_t def_cmd_binds[] = {
 
+  { {  MOUSE_BTN0_DBL, 0 }, "vo_fullscreen" },
   { {  MOUSE_BTN3, 0 }, "seek 10" },
   { {  MOUSE_BTN4, 0 }, "seek -10" },
   { {  MOUSE_BTN5, 0 }, "volume 1" },
@@ -495,6 +498,10 @@
 static mp_cmd_t* ar_cmd = NULL;
 static unsigned int ar_delay = 100, ar_rate = 8, last_ar = 0;
 
+// Mouse button doubleclick time, default value may be overridden
+// during the GUI initialization.
+static unsigned int doubleclick_time = 300;
+
 static int use_joystick = 1, use_lirc = 1, use_lircc = 1;
 static char* config_file = "input.conf";
 
@@ -877,9 +884,14 @@
   
 
 static char*
-mp_input_find_bind_for_key(mp_cmd_bind_t* binds, int n,int* keys) {
+mp_input_find_bind_for_key(int n, int* keys) {
+  mp_cmd_bind_t* binds;
   int j;
 
+  binds = cmd_binds;
+  if (binds == NULL)
+    return NULL;
+
   for(j = 0; binds[j].cmd != NULL; j++) {
     if(n > 0) {
       int found = 1,s;
@@ -903,24 +915,27 @@
 
 static mp_cmd_t*
 mp_input_get_cmd_from_keys(int n,int* keys, int paused) {
-  char* cmd = NULL;
+  char* cmd;
   mp_cmd_t* ret;
 
-  if(cmd_binds)
-    cmd = mp_input_find_bind_for_key(cmd_binds,n,keys);
-  if(cmd == NULL)
-    cmd = mp_input_find_bind_for_key(def_cmd_binds,n,keys);
+  for(;;) {
+    cmd = mp_input_find_bind_for_key(n,keys);
+    // Found a command.
+    if(cmd != NULL) {
+      if (strcmp(cmd, MP_CMD_TXT_NO_COMMAND) == 0)
+        return NULL;
+      break;
+    }
 
-  if(cmd == NULL) {
+    // Ignore unbound key.
     mp_msg(MSGT_INPUT,MSGL_WARN,MSGTR_NoBindFound,mp_input_get_key_name(keys[0]));
-    if(n > 1) {
-      int s;
-      for(s=1; s < n; s++)
-	mp_msg(MSGT_INPUT,MSGL_WARN,"-%s",mp_input_get_key_name(keys[s]));
-    }
     mp_msg(MSGT_INPUT,MSGL_WARN,"                         \n");
-    return NULL;
+    keys++;
+    n--;
+    if(n<=0)
+      return NULL;
   }
+
   ret =  mp_input_parse_cmd(cmd);
   if(!ret) {
     mp_msg(MSGT_INPUT,MSGL_ERR,MSGTR_INPUT_INPUT_ErrInvalidCommandForKey,mp_input_get_key_name(key_down[0]));
@@ -1382,6 +1397,8 @@
 void
 mp_input_bind_keys(int keys[MP_MAX_KEY_DOWN+1], char* cmd) {
   int i = 0,j;
+  int key;
+  char* other_cmd;
   mp_cmd_bind_t* bind = NULL;
 
 #ifdef MP_DEBUG
@@ -1389,6 +1406,23 @@
   assert(cmd != NULL);
 #endif
 
+  /* When binding a command to a mouse button doubleclick, if the
+   * corresponding single click is not bound, bind it to the
+   * command which does nothing in order to avoid logging command
+   * not found on the first click of the doubleclick. */
+  for(j = 0 ; (key = keys[j]) != 0 ; j++) {
+    if (MOUSE_BTN0_DBL <= key && key <= MOUSE_BTN_LAST_DBL) {
+      key = MOUSE_BTN0 + key - MOUSE_BTN0_DBL;
+      other_cmd = mp_input_find_bind_for_key(1, &key);
+      if (other_cmd == NULL) {
+        int other_cmd_keys[2];
+        other_cmd_keys[0] = key;
+        other_cmd_keys[1] = 0;
+        mp_input_bind_keys(other_cmd_keys, MP_CMD_TXT_NO_COMMAND);
+      }
+    }
+  }
+
   if(cmd_binds) {
     for(i = 0; cmd_binds[i].cmd != NULL ; i++) {
       for(j = 0 ; cmd_binds[i].input[j] == keys[j]  && keys[j] != 0 ; j++)
@@ -1594,6 +1628,9 @@
 mp_input_init(int use_gui) {
   char* file;
 
+  // Bind default keys, thus ensure cmd_binds is allocated.
+  mp_input_add_binds(def_cmd_binds);
+
 #ifdef HAVE_NEW_GUI  
   if(use_gui)
     mp_input_add_binds(gui_def_cmd_binds);
@@ -1743,3 +1780,67 @@
   mp_cmd_free(cmd);
   return 0;
 }
+
+unsigned int
+mp_input_get_doubleclick_time() {
+  return doubleclick_time;
+}
+
+void
+mp_input_set_doubleclick_time(unsigned int time) {
+  doubleclick_time = time;
+}
+
+
+extern void mplayer_put_key_internal(int code);
+
+static unsigned int mouse_button_press_timer = 0;
+static int last_pressed_mouse_button;
+
+// This puts key layer filter events.
+// It can translate the event into another one.
+void mplayer_put_key(int code) {
+  unsigned int now;
+  int btn, ignore;
+
+  ignore = code & MP_VETOED_KEY;
+  code &= ~MP_VETOED_KEY;
+
+  // Check mouse button press event.
+  if ((MOUSE_BTN0 | MP_KEY_DOWN) <= code &&
+      code <= (MOUSE_BTN_LAST | MP_KEY_DOWN)) {
+    btn = code - (MOUSE_BTN0 | MP_KEY_DOWN);
+    // Translate mouse wheel: Interpret press event as release event.
+    if (btn == 3 || btn == 4)
+      code = MOUSE_BTN0 + btn;
+    // Detect mouse doubleclick.
+    else {
+      now = GetTimerMS();
+      if (btn == last_pressed_mouse_button &&
+          now - mouse_button_press_timer <= mp_input_get_doubleclick_time()) {
+        mouse_button_press_timer = 0;
+        // Translate mouse doubleclick: Create new event.
+        code = MOUSE_BTN0_DBL + btn;
+        ignore = 0;
+      }
+      else {
+        mouse_button_press_timer = now;
+        last_pressed_mouse_button = btn;
+      }
+    }
+  }
+  // Translate mouse wheel: Ignore simulated release event.
+  else if (code == MOUSE_BTN3 || code == MOUSE_BTN4)
+    ignore = 1;
+  // Translate mouse wheel: Convert to mouse button release event.
+  else if (code == MOUSE_WHL_UP)
+    code = MOUSE_BTN3;
+  else if (code == MOUSE_WHL_DOWN)
+    code = MOUSE_BTN4;
+  // Process mouse doubleclick.
+  else if (MOUSE_BTN0_DBL <= code && code <= MOUSE_BTN_LAST_DBL)
+    mouse_button_press_timer = 0;
+
+  if (!ignore)
+    mplayer_put_key_internal(code);
+}
Index: input/input.h
===================================================================
--- input/input.h	(revision 19814)
+++ input/input.h	(working copy)
@@ -147,6 +147,8 @@
 #define MP_KEY_DOWN (1<<29)
 // Use this when the key shouldn't be auto-repeated (like mouse buttons)
 #define MP_NO_REPEAT_KEY (1<<28)
+// Use this to notify of the key event while performing no action.
+#define MP_VETOED_KEY (1<<27)
 
 #ifndef MP_MAX_KEY_DOWN
 #define MP_MAX_KEY_DOWN 32
@@ -260,3 +262,9 @@
 int
 mp_input_check_interrupt(int time);
 
+// mouse button doubleclick time
+unsigned int
+mp_input_get_doubleclick_time();
+
+void
+mp_input_set_doubleclick_time(unsigned int time);
Index: input/mouse.h
===================================================================
--- input/mouse.h	(revision 19814)
+++ input/mouse.h	(working copy)
@@ -11,8 +11,14 @@
 #define MOUSE_BTN7 (MOUSE_BASE+7)
 #define MOUSE_BTN8 (MOUSE_BASE+8)
 #define MOUSE_BTN9 (MOUSE_BASE+9)
+#define MOUSE_BTN_LAST MOUSE_BTN9
+
+#define MOUSE_BASE_EXT (0x300|MP_NO_REPEAT_KEY)
 
-#define MOUSE_BASE_DBL (0x300|MP_NO_REPEAT_KEY)
+#define MOUSE_WHL_UP   (MOUSE_BASE_EXT+0)
+#define MOUSE_WHL_DOWN (MOUSE_BASE_EXT+1)
+
+#define MOUSE_BASE_DBL (MOUSE_BASE_EXT+2)
 #define MOUSE_BTN0_DBL (MOUSE_BASE_DBL+0)
 #define MOUSE_BTN1_DBL (MOUSE_BASE_DBL+1)
 #define MOUSE_BTN2_DBL (MOUSE_BASE_DBL+2)
@@ -23,3 +29,4 @@
 #define MOUSE_BTN7_DBL (MOUSE_BASE_DBL+7)
 #define MOUSE_BTN8_DBL (MOUSE_BASE_DBL+8)
 #define MOUSE_BTN9_DBL (MOUSE_BASE_DBL+9)
+#define MOUSE_BTN_LAST_DBL MOUSE_BTN9_DBL
Index: libvo/vo_directx.c
===================================================================
--- libvo/vo_directx.c	(revision 19814)
+++ libvo/vo_directx.c	(working copy)
@@ -1019,9 +1019,9 @@
 				break;
 			int x = GET_WHEEL_DELTA_WPARAM(wParam);
 			if (x > 0)
-				mplayer_put_key(MOUSE_BTN3);
+				mplayer_put_key(MOUSE_WHL_UP);
 			else
-				mplayer_put_key(MOUSE_BTN4);
+				mplayer_put_key(MOUSE_WHL_DOWN);
 			break;
 		}
         case WM_XBUTTONDOWN:
Index: libvo/vo_quartz.c
===================================================================
--- libvo/vo_quartz.c	(revision 19814)
+++ libvo/vo_quartz.c	(working copy)
@@ -300,9 +300,9 @@
 				if(part == inContent)
 				{
 					if(wheel > 0)
-						mplayer_put_key(MOUSE_BTN3);
+						mplayer_put_key(MOUSE_WHL_UP);
 					else
-						mplayer_put_key(MOUSE_BTN4);
+						mplayer_put_key(MOUSE_WHL_DOWN);
 				}
 			}
 			break;
Index: libvo/vo_sdl.c
===================================================================
--- libvo/vo_sdl.c	(revision 19814)
+++ libvo/vo_sdl.c	(working copy)
@@ -1189,10 +1189,7 @@
 			case SDL_MOUSEBUTTONDOWN:
 				if(vo_nomouse_input)
 				    break;
-				if(event.button.button == 4 || event.button.button == 5)
-					mplayer_put_key(MOUSE_BASE+event.button.button-1);
-				else
-					mplayer_put_key((MOUSE_BASE+event.button.button-1) | MP_KEY_DOWN);
+				mplayer_put_key((MOUSE_BTN0+event.button.button-1) | MP_KEY_DOWN);
 				break;			    
 		
 			case SDL_MOUSEBUTTONUP:
@@ -1198,7 +1195,7 @@
 			case SDL_MOUSEBUTTONUP:
 				if(vo_nomouse_input)
 				    break;
-				mplayer_put_key(MOUSE_BASE+event.button.button-1);
+				mplayer_put_key(MOUSE_BTN0+event.button.button-1);
 				break;
 	
 			/* graphics mode selection shortcuts */
Index: libvo/w32_common.c
===================================================================
--- libvo/w32_common.c	(revision 19814)
+++ libvo/w32_common.c	(working copy)
@@ -114,9 +114,9 @@
 	    if (!vo_nomouse_input) {
 		int x = GET_WHEEL_DELTA_WPARAM(wParam);
 		if (x > 0)
-		    mplayer_put_key(MOUSE_BTN3);
+		    mplayer_put_key(MOUSE_WHL_UP);
 		else
-		    mplayer_put_key(MOUSE_BTN4);
+		    mplayer_put_key(MOUSE_WHL_DOWN);
 		break;
 	    }
     }
Index: libvo/x11_common.c
===================================================================
--- libvo/x11_common.c	(revision 19814)
+++ libvo/x11_common.c	(working copy)
@@ -1098,17 +1098,8 @@
                     mouse_waiting_hide = 1;
                     mouse_timer = GetTimerMS();
                 }
-                // Ignore mouse whell press event
-                if (Event.xbutton.button > 3)
-                {
-                    mplayer_put_key(MOUSE_BTN0 + Event.xbutton.button - 1);
-                    break;
-                }
 #ifdef HAVE_NEW_GUI
-                // Ignor mouse button 1 - 3 under gui 
-                if (use_gui && (Event.xbutton.button >= 1)
-                    && (Event.xbutton.button <= 3))
-                    break;
+                if ( use_gui ) { break; }
 #endif
                 mplayer_put_key((MOUSE_BTN0 + Event.xbutton.button -
                                  1) | MP_KEY_DOWN);
@@ -1121,10 +1112,7 @@
                     mouse_timer = GetTimerMS();
                 }
 #ifdef HAVE_NEW_GUI
-                // Ignor mouse button 1 - 3 under gui 
-                if (use_gui && (Event.xbutton.button >= 1)
-                    && (Event.xbutton.button <= 3))
-                    break;
+                if ( use_gui ) { break; }
 #endif
                 mplayer_put_key(MOUSE_BTN0 + Event.xbutton.button - 1);
                 break;


More information about the MPlayer-dev-eng mailing list